Skip to content

Commit

Permalink
* render Q3 shader based skyboxes
Browse files Browse the repository at this point in the history
logic: load 6 skybox textures when shader gets used by scene, don't unload dynamically, just on 'flush'
texture browser only uses normal preview image and doesn't trigger potentially heavy box loading
also fix R_ResampleTexture for [2+x upscaling
  • Loading branch information
Garux committed Jul 18, 2022
1 parent 22377bb commit d3e48d8
Show file tree
Hide file tree
Showing 11 changed files with 219 additions and 21 deletions.
1 change: 1 addition & 0 deletions include/iglrender.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class OpenGLState
GLint m_texture5;
GLint m_texture6;
GLint m_texture7;
GLint m_textureSkyBox;
Vector4 m_colour;
GLenum m_blend_src, m_blend_dst;
GLenum m_depthfunc;
Expand Down
1 change: 1 addition & 0 deletions include/ishaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class IShader
virtual void DecRef() = 0;
// get/set the qtexture_t* Radiant uses to represent this shader object
virtual qtexture_t* getTexture() const = 0;
virtual qtexture_t* getSkyBox() = 0;
virtual qtexture_t* getDiffuse() const = 0;
virtual qtexture_t* getBump() const = 0;
virtual qtexture_t* getSpecular() const = 0;
Expand Down
3 changes: 2 additions & 1 deletion include/itextures.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ class LoadImageCallback
public:
void* m_environment;
LoadFunc m_func;
bool m_skybox;

LoadImageCallback( void* environment, LoadFunc func ) : m_environment( environment ), m_func( func ){
LoadImageCallback( void* environment, LoadFunc func, bool skybox = false ) : m_environment( environment ), m_func( func ), m_skybox( skybox ){
}
Image* loadImage( const char* name ) const {
return m_func( m_environment, name );
Expand Down
26 changes: 26 additions & 0 deletions plugins/shaders/shaders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ class ShaderTemplate
ShaderParameters m_params;

TextureExpression m_textureName;
TextureExpression m_skyBox;
TextureExpression m_diffuse;
TextureExpression m_bump;
ShaderValue m_heightmapScale;
Expand Down Expand Up @@ -838,6 +839,7 @@ class CShader : public IShader
CopiedString m_Name;

qtexture_t* m_pTexture;
qtexture_t* m_pSkyBox;
qtexture_t* m_notfound;
qtexture_t* m_pDiffuse;
float m_heightmapScale;
Expand All @@ -860,6 +862,7 @@ class CShader : public IShader
m_blendFunc( BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA ),
m_bInUse( false ){
m_pTexture = 0;
m_pSkyBox = 0;
m_pDiffuse = 0;
m_pBump = 0;
m_pSpecular = 0;
Expand Down Expand Up @@ -893,6 +896,13 @@ class CShader : public IShader
qtexture_t* getTexture() const {
return m_pTexture;
}
qtexture_t* getSkyBox() override {
/* load skybox if only used */
if( m_pSkyBox == nullptr && !m_template.m_skyBox.empty() )
m_pSkyBox = GlobalTexturesCache().capture( LoadImageCallback( 0, GlobalTexturesCache().defaultLoader().m_func, true ), m_template.m_skyBox.c_str() );

return m_pSkyBox;
}
qtexture_t* getDiffuse() const {
return m_pDiffuse;
}
Expand Down Expand Up @@ -966,6 +976,10 @@ class CShader : public IShader
GlobalTexturesCache().release( m_notfound );
}

if ( m_pSkyBox != 0 ) {
GlobalTexturesCache().release( m_pSkyBox );
}

unrealiseLighting();
}

Expand Down Expand Up @@ -1220,6 +1234,18 @@ bool ShaderTemplate::parseQuake3( Tokeniser& tokeniser ){

RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, m_AlphaRef ) );
}
else if ( string_equal_nocase( token, "skyparms" ) ) {
const char* sky = tokeniser.getToken();

if ( sky == 0 ) {
Tokeniser_unexpectedError( tokeniser, sky, "#skyparms" );
return false;
}

if( !string_equal( sky, "-" ) ){
m_skyBox = sky;
}
}
else if ( string_equal_nocase( token, "cull" ) ) {
const char* cull = tokeniser.getToken();

Expand Down
3 changes: 2 additions & 1 deletion radiant/camwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2091,7 +2091,8 @@ void CamWnd::Cam_Draw(){
| RENDER_LIGHTING
| RENDER_TEXTURE
| RENDER_SMOOTH
| RENDER_SCALED;
| RENDER_SCALED
| RENDER_PROGRAM;
break;
case cd_lighting:
globalstate |= RENDER_FILL
Expand Down
111 changes: 106 additions & 5 deletions radiant/renderstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,69 @@ class GLSLDepthFillProgram : public GLProgram
GLSLDepthFillProgram g_depthFillGLSL;


class GLSLSkyboxProgram : public GLProgram
{
public:
GLhandleARB m_program;
GLint u_view_origin;

GLSLSkyboxProgram() : m_program( 0 ){
}

void create(){
// create program
m_program = glCreateProgramObjectARB();

// create shader
{
StringOutputStream filename( 256 );
createShader( m_program, filename( GlobalRadiant().getAppPath(), "gl/skybox_vp.glsl" ), GL_VERTEX_SHADER_ARB );
createShader( m_program, filename( GlobalRadiant().getAppPath(), "gl/skybox_fp.glsl" ), GL_FRAGMENT_SHADER_ARB );
}

GLSLProgram_link( m_program );
GLSLProgram_validate( m_program );

glUseProgramObjectARB( m_program );

u_view_origin = glGetUniformLocationARB( m_program, "u_view_origin" );

glUseProgramObjectARB( 0 );

GlobalOpenGL_debugAssertNoErrors();
}

void destroy(){
glDeleteObjectARB( m_program );
m_program = 0;
}

void enable(){
glUseProgramObjectARB( m_program );

GlobalOpenGL_debugAssertNoErrors();

debug_string( "enable skybox" );
}

void disable(){
glUseProgramObjectARB( 0 );

GlobalOpenGL_debugAssertNoErrors();

debug_string( "disable skybox" );
}

void setParameters( const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light ){
glUniform3fARB( u_view_origin, viewer.x(), viewer.y(), viewer.z() );

GlobalOpenGL_debugAssertNoErrors();
}
};

GLSLSkyboxProgram g_skyboxGLSL;


// ARB path

void createProgram( const char* filename, GLenum type ){
Expand Down Expand Up @@ -790,6 +853,9 @@ inline bool OpenGLState_less( const OpenGLState& self, const OpenGLState& other
if ( self.m_texture7 != other.m_texture7 ) {
return self.m_texture7 < other.m_texture7;
}
if ( self.m_textureSkyBox != other.m_textureSkyBox ) {
return self.m_textureSkyBox < other.m_textureSkyBox;
}
//! Sort by state bit-vector.
if ( self.m_state != other.m_state ) {
return self.m_state < other.m_state;
Expand All @@ -809,6 +875,7 @@ void OpenGLState_constructDefault( OpenGLState& state ){
state.m_texture5 = 0;
state.m_texture6 = 0;
state.m_texture7 = 0;
state.m_textureSkyBox = 0;

state.m_colour[0] = 1;
state.m_colour[1] = 1;
Expand Down Expand Up @@ -1158,7 +1225,7 @@ class OpenGLShaderCache final : public ShaderCache, public TexturesCacheObserver

bool m_lightingEnabled;
bool m_lightingSupported;
bool m_useShaderLanguage;
const bool m_useShaderLanguage;

public:
OpenGLShaderCache() :
Expand Down Expand Up @@ -1302,8 +1369,9 @@ class OpenGLShaderCache final : public ShaderCache, public TexturesCacheObserver
}
debug_string( "end rendering" );

OpenGLState reset = current; /* popmatrix after RENDER_TEXT */
reset.m_state = current.m_state & ~RENDER_TEXT;
OpenGLState reset = current; /* reset some states */
reset.m_state = current.m_state & ~RENDER_TEXT; /* popmatrix after RENDER_TEXT */
reset.m_program = nullptr; /* disable shader */
OpenGLState_apply( reset, current, globalstate );
}
void realise(){
Expand All @@ -1320,6 +1388,9 @@ class OpenGLShaderCache final : public ShaderCache, public TexturesCacheObserver
}
}

if( lightingSupported() )
g_skyboxGLSL.create();

for ( Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i )
{
if ( !( *i ).value.empty() ) {
Expand Down Expand Up @@ -1347,6 +1418,8 @@ class OpenGLShaderCache final : public ShaderCache, public TexturesCacheObserver
g_depthFillARB.destroy();
}
}
if( GlobalOpenGL().contextValid && lightingSupported() )
g_skyboxGLSL.destroy();
}
}
bool realised(){
Expand Down Expand Up @@ -1645,7 +1718,7 @@ void OpenGLState_apply( const OpenGLState& self, OpenGLState& current, unsigned
if ( program != current.m_program ) {
if ( current.m_program != 0 ) {
current.m_program->disable();
glColor4fv( vector4_to_array( current.m_colour ) );
//why? glColor4fv( vector4_to_array( current.m_colour ) );
debug_colour( "cleaning program" );
}

Expand Down Expand Up @@ -1888,6 +1961,16 @@ void OpenGLState_apply( const OpenGLState& self, OpenGLState& current, unsigned
}


if( current.m_textureSkyBox != self.m_textureSkyBox ){
if ( GlobalOpenGL().GL_1_3() ) {
glActiveTexture( GL_TEXTURE0 );
glClientActiveTexture( GL_TEXTURE0 );
}
glBindTexture( GL_TEXTURE_CUBE_MAP, self.m_textureSkyBox );
GlobalOpenGL_debugAssertNoErrors();
current.m_textureSkyBox = self.m_textureSkyBox;
}

if ( state & RENDER_TEXTURE && self.m_colour[3] != current.m_colour[3] ) {
debug_colour( "setting alpha" );
glColor4f( 1,1,1,self.m_colour[3] );
Expand Down Expand Up @@ -1932,6 +2015,11 @@ void OpenGLState_apply( const OpenGLState& self, OpenGLState& current, unsigned
void Renderables_flush( OpenGLStateBucket::Renderables& renderables, OpenGLState& current, unsigned int globalstate, const Vector3& viewer ){
const Matrix4* transform = 0;
glPushMatrix();

if ( current.m_program != 0 && current.m_textureSkyBox != 0 && globalstate & RENDER_PROGRAM ) {
current.m_program->setParameters( viewer, g_matrix4_identity, g_vector3_identity, g_vector3_identity, g_matrix4_identity );
}

for ( OpenGLStateBucket::Renderables::const_iterator i = renderables.begin(); i != renderables.end(); ++i )
{
//qglLoadMatrixf(i->m_transform);
Expand Down Expand Up @@ -2421,6 +2509,19 @@ void OpenGLShader::construct( const char* name ){
bumpPass.m_blend_src = GL_ONE;
bumpPass.m_blend_dst = GL_ONE;
}
// g_ShaderCache->lightingSupported() as in GLSL is available
else if( m_shader->getSkyBox() != nullptr && m_shader->getSkyBox()->texture_number != 0 && g_ShaderCache->lightingSupported() )
{
state.m_texture = m_shader->getTexture()->texture_number;
state.m_textureSkyBox = m_shader->getSkyBox()->texture_number;

state.m_state = RENDER_FILL | RENDER_CULLFACE | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE | RENDER_COLOURWRITE | RENDER_PROGRAM;
state.m_colour.vec3() = m_shader->getTexture()->color;
state.m_colour[3] = 1.0f;
state.m_sort = OpenGLState::eSortFullbright;

state.m_program = &g_skyboxGLSL;
}
else
{
state.m_texture = m_shader->getTexture()->texture_number;
Expand Down Expand Up @@ -2461,7 +2562,7 @@ void OpenGLShader::construct( const char* name ){
break;
}
}
reinterpret_cast<Vector3&>( state.m_colour ) = m_shader->getTexture()->color;
state.m_colour.vec3() = m_shader->getTexture()->color;
state.m_colour[3] = 1.0f;

if ( ( m_shader->getFlags() & QER_TRANS ) != 0 ) {
Expand Down
2 changes: 2 additions & 0 deletions radiant/texmanip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ void R_ResampleTexture( const void *indata, int inwidth, int inheight, void *out
oldy = yi;
}
memcpy( out, row1, outwidth4 );
out += outwidth4;
}
}
}
Expand Down Expand Up @@ -297,6 +298,7 @@ void R_ResampleTexture( const void *indata, int inwidth, int inheight, void *out
oldy = yi;
}
memcpy( out, row1, outwidth3 );
out += outwidth3;
}
}
}
Expand Down
Loading

1 comment on commit d3e48d8

@Garux
Copy link
Owner Author

@Garux Garux commented on d3e48d8 Jul 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#96

Please sign in to comment.