/* ================== GL_BindProgram ================== */ void GL_BindProgram (program_t *program){ if (!program){ if (!glState.program) return; glState.program = NULL; qglUseProgram(0); return; } if (glState.program == program) return; glState.program = program; qglUseProgram(program->programId); }
int GL_UseProgram(GLuint program) { if (glDsaState.program == program) return 0; qglUseProgram(program); glDsaState.program = program; return 1; }
/* * @brief */ void R_UseProgram(r_program_t *prog) { if (!qglUseProgram || r_state.active_program == prog) return; r_state.active_program = prog; if (prog) { qglUseProgram(prog->id); if (prog->Use) // invoke use function prog->Use(); } else { qglUseProgram(0); } R_GetError(NULL); }
void R_UseProgram (r_program_t* prog) { if (!qglUseProgram || r_state.active_program == prog) return; if (!r_state.active_program) refdef.FFPToShaderCount++; else if (!prog) refdef.shaderToFFPCount++; else refdef.shaderToShaderCount++; r_state.active_program = prog; if (prog) { qglUseProgram(prog->id); if (prog->use) /* invoke use function */ prog->use(prog); } else { qglUseProgram(0); } }
/* ================================================================================================ idRenderProgManager::LoadGLSLProgram ================================================================================================ */ void idRenderProgManager::LoadGLSLProgram( const int programIndex, const int vertexShaderIndex, const int fragmentShaderIndex ) { glslProgram_t & prog = glslPrograms[programIndex]; if ( prog.progId != INVALID_PROGID ) { return; // Already loaded } GLuint vertexProgID = ( vertexShaderIndex != -1 ) ? vertexShaders[ vertexShaderIndex ].progId : INVALID_PROGID; GLuint fragmentProgID = ( fragmentShaderIndex != -1 ) ? fragmentShaders[ fragmentShaderIndex ].progId : INVALID_PROGID; const GLuint program = qglCreateProgram(); if ( program ) { if ( vertexProgID != INVALID_PROGID ) { qglAttachShader( program, vertexProgID ); } if ( fragmentProgID != INVALID_PROGID ) { qglAttachShader( program, fragmentProgID ); } // bind vertex attribute locations for ( int i = 0; attribsPC[i].glsl != NULL; i++ ) { if ( ( attribsPC[i].flags & AT_VS_IN ) != 0 ) { qglBindAttribLocation( program, attribsPC[i].bind, attribsPC[i].glsl ); } } qglLinkProgram( program ); int infologLength = 0; qglGetProgramiv( program, GL_INFO_LOG_LENGTH, &infologLength ); if ( infologLength > 1 ) { char * infoLog = (char *)malloc( infologLength ); int charsWritten = 0; qglGetProgramInfoLog( program, infologLength, &charsWritten, infoLog ); // catch the strings the ATI and Intel drivers output on success if ( strstr( infoLog, "Vertex shader(s) linked, fragment shader(s) linked." ) != NULL || strstr( infoLog, "No errors." ) != NULL ) { //idLib::Printf( "render prog %s from %s linked\n", GetName(), GetFileName() ); } else { idLib::Printf( "While linking GLSL program %d with vertexShader %s and fragmentShader %s\n", programIndex, ( vertexShaderIndex >= 0 ) ? vertexShaders[vertexShaderIndex].name.c_str() : "<Invalid>", ( fragmentShaderIndex >= 0 ) ? fragmentShaders[ fragmentShaderIndex ].name.c_str() : "<Invalid>" ); idLib::Printf( "%s\n", infoLog ); } free( infoLog ); } } int linked = GL_FALSE; qglGetProgramiv( program, GL_LINK_STATUS, &linked ); if ( linked == GL_FALSE ) { qglDeleteProgram( program ); idLib::Error( "While linking GLSL program %d with vertexShader %s and fragmentShader %s\n", programIndex, ( vertexShaderIndex >= 0 ) ? vertexShaders[vertexShaderIndex].name.c_str() : "<Invalid>", ( fragmentShaderIndex >= 0 ) ? fragmentShaders[ fragmentShaderIndex ].name.c_str() : "<Invalid>" ); return; } if ( r_useUniformArrays.GetBool() ) { prog.vertexUniformArray = qglGetUniformLocation( program, VERTEX_UNIFORM_ARRAY_NAME ); prog.fragmentUniformArray = qglGetUniformLocation( program, FRAGMENT_UNIFORM_ARRAY_NAME ); assert( prog.vertexUniformArray != -1 || vertexShaderIndex < 0 || vertexShaders[vertexShaderIndex].uniforms.Num() == 0 ); assert( prog.fragmentUniformArray != -1 || fragmentShaderIndex < 0 || fragmentShaders[fragmentShaderIndex].uniforms.Num() == 0 ); } else { // store the uniform locations after we have linked the GLSL program prog.uniformLocations.Clear(); for ( int i = 0; i < RENDERPARM_TOTAL; i++ ) { const char * parmName = GetGLSLParmName( i ); GLint loc = qglGetUniformLocation( program, parmName ); if ( loc != -1 ) { glslUniformLocation_t uniformLocation; uniformLocation.parmIndex = i; uniformLocation.uniformIndex = loc; prog.uniformLocations.Append( uniformLocation ); } } // store the USER uniform locations for ( int i = 0; i < MAX_GLSL_USER_PARMS; i++ ) { const char * parmName = GetGLSLParmName( RENDERPARM_USER + i ); GLint loc = qglGetUniformLocation( program, parmName ); if ( loc != -1 ) { glslUniformLocation_t uniformLocation; uniformLocation.parmIndex = RENDERPARM_USER + i; uniformLocation.uniformIndex = loc; prog.uniformLocations.Append( uniformLocation ); } } // sort the uniforms based on index prog.uniformLocations.SortWithTemplate( idSort_QuickUniforms() ); } // get the uniform buffer binding for skinning joint matrices GLint blockIndex = qglGetUniformBlockIndex( program, "matrices_ubo" ); if ( blockIndex != -1 ) { qglUniformBlockBinding( program, blockIndex, 0 ); } // set the texture unit locations once for the render program. We only need to do this once since we only link the program once qglUseProgram( program ); for ( int i = 0; i < MAX_PROG_TEXTURE_PARMS; ++i ) { GLint loc = qglGetUniformLocation( program, va( "samp%d", i ) ); if ( loc != -1 ) { qglUniform1i( loc, i ); } } idStr programName = vertexShaders[ vertexShaderIndex ].name; programName.StripFileExtension(); prog.name = programName; prog.progId = program; prog.fragmentShaderIndex = fragmentShaderIndex; prog.vertexShaderIndex = vertexShaderIndex; }
//Does a water warp on the pre-fragmented glpoly_t chain void EmitWaterPolys (msurface_t *fa) { glpoly_t *p; float *v, s, t, os, ot; int i; byte *col; extern cvar_t r_telecolor, r_watercolor, r_slimecolor, r_lavacolor; float wateralpha = bound((1 - r_refdef2.max_watervis), r_wateralpha.value, 1); vec3_t nv; GLint shader, u_gamma, u_contrast; GL_DisableMultitexture(); if (gl_fogenable.value) glEnable(GL_FOG); GL_Bind (fa->texinfo->texture->gl_texturenum); /* FIXME: do the uniforms somewhere else */ shader = glsl_shaders[SHADER_TURB].shader; qglUseProgram(shader); u_gamma = qglGetUniformLocation(shader, "gamma"); u_contrast = qglGetUniformLocation(shader, "contrast"); qglUniform1f(u_gamma, v_gamma.value); qglUniform1f(u_contrast, v_contrast.value); if (r_fastturb.value) { GL_Bind(whitetexture); if (strstr (fa->texinfo->texture->name, "water") || strstr (fa->texinfo->texture->name, "mwat")) col = r_watercolor.color; else if (strstr (fa->texinfo->texture->name, "slime")) col = r_slimecolor.color; else if (strstr (fa->texinfo->texture->name, "lava")) col = r_lavacolor.color; else if (strstr (fa->texinfo->texture->name, "tele")) col = r_telecolor.color; else col = (byte *) &fa->texinfo->texture->flatcolor3ub; glColor3ubv (col); if (wateralpha < 1.0 && wateralpha >= 0) { glEnable (GL_BLEND); col[3] = wateralpha*255; glColor4ubv (col); // 1, 1, 1, wateralpha glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); if (wateralpha < 0.9) glDepthMask (GL_FALSE); } EmitFlatWaterPoly (fa); if (wateralpha < 1.0 && wateralpha >= 0) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glColor3ubv (color_white); glDisable (GL_BLEND); if (wateralpha < 0.9) glDepthMask (GL_TRUE); } glColor3ubv (color_white); } else { for (p = fa->polys; p; p = p->next) { glBegin(GL_POLYGON); for (i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE) { os = v[3]; ot = v[4]; s = os + SINTABLE_APPROX(ot * 2 + r_refdef2.time); s *= (1.0 / 64); t = ot + SINTABLE_APPROX(os * 2 + r_refdef2.time); t *= (1.0 / 64); //VULT RIPPLE : Not sure where this came from first, but I've seen in it more than one engine //I got this one from the QMB engine though VectorCopy(v, nv); //Over 20 this setting gets pretty cheaty if (amf_waterripple.value && (cls.demoplayback || cl.spectator) && !strstr (fa->texinfo->texture->name, "tele")) nv[2] = v[2] + (bound(0, amf_waterripple.value, 20)) *sin(v[0]*0.02+r_refdef2.time)*sin(v[1]*0.02+r_refdef2.time)*sin(v[2]*0.02+r_refdef2.time); glTexCoord2f (s, t); glVertex3fv (nv); } glEnd(); } } qglUseProgram(0); if (gl_fogenable.value) glDisable(GL_FOG); }
/* ================== GL_SetDefaultState ================== */ void GL_SetDefaultState (){ int i; QGL_LogPrintf("---------- GL_SetDefaultState ----------\n"); // Reset the state manager glState.projectionMatrixIdentity = true; glState.modelviewMatrixIdentity = true; for (i = 0; i < MAX_TEXTURE_UNITS; i++) glState.textureMatrixIdentity[i] = true; for (i = 0; i < MAX_TEXTURE_UNITS; i++) glState.texture[i] = NULL; glState.program = NULL; glState.indexBuffer = NULL; glState.vertexBuffer = NULL; glState.viewportX = 0; glState.viewportY = 0; glState.viewportWidth = glConfig.videoWidth; glState.viewportHeight = glConfig.videoHeight; glState.scissorX = 0; glState.scissorY = 0; glState.scissorWidth = glConfig.videoWidth; glState.scissorHeight = glConfig.videoHeight; glState.depthBoundsMin = 0.0f; glState.depthBoundsMax = 1.0f; glState.texUnit = 0; for (i = 0; i < MAX_TEXTURE_UNITS; i++){ glState.texTarget[i] = 0; glState.texEnv[i] = GL_MODULATE; glState.texGen[i][0] = GL_OBJECT_LINEAR; glState.texGen[i][1] = GL_OBJECT_LINEAR; glState.texGen[i][2] = GL_OBJECT_LINEAR; glState.texGen[i][3] = GL_OBJECT_LINEAR; } glState.cullFace = false; glState.polygonOffsetFill = false; glState.polygonOffsetLine = false; glState.blend = false; glState.alphaTest = false; glState.depthTest = false; glState.stencilTest = false; for (i = 0; i < MAX_TEXTURE_UNITS; i++){ glState.textureGen[i][0] = false; glState.textureGen[i][1] = false; glState.textureGen[i][2] = false; glState.textureGen[i][3] = false; } glState.cullMode = GL_FRONT; glState.polygonMode = GL_FILL; glState.polygonOffsetFactor = 0.0f; glState.polygonOffsetUnits = 0.0f; glState.blendSrc = GL_ONE; glState.blendDst = GL_ZERO; glState.blendMode = GL_FUNC_ADD; glState.alphaFunc = GL_GREATER; glState.alphaFuncRef = 0.0f; glState.depthFunc = GL_LEQUAL; glState.stencilFunc[0] = GL_ALWAYS; glState.stencilFunc[1] = GL_ALWAYS; glState.stencilFuncRef[0] = 0; glState.stencilFuncRef[1] = 0; glState.stencilFuncMask[0] = 255; glState.stencilFuncMask[1] = 255; glState.stencilOpFail[0] = GL_KEEP; glState.stencilOpFail[1] = GL_KEEP; glState.stencilOpZFail[0] = GL_KEEP; glState.stencilOpZFail[1] = GL_KEEP; glState.stencilOpZPass[0] = GL_KEEP; glState.stencilOpZPass[1] = GL_KEEP; glState.depthMin = 0.0f; glState.depthMax = 1.0f; glState.colorMask[0] = GL_TRUE; glState.colorMask[1] = GL_TRUE; glState.colorMask[2] = GL_TRUE; glState.colorMask[3] = GL_TRUE; glState.depthMask = GL_TRUE; glState.stencilMask[0] = 255; glState.stencilMask[1] = 255; // Set default state qglMatrixMode(GL_PROJECTION); qglLoadIdentity(); qglMatrixMode(GL_MODELVIEW); qglLoadIdentity(); for (i = MAX_TEXTURE_UNITS - 1; i >= 0; i--){ if (i >= glConfig.maxTextureImageUnits) continue; if (i >= glConfig.maxTextureUnits){ qglActiveTexture(GL_TEXTURE0 + i); qglBindTexture(GL_TEXTURE_2D, 0); qglBindTexture(GL_TEXTURE_3D, 0); qglBindTexture(GL_TEXTURE_CUBE_MAP, 0); qglBindTexture(GL_TEXTURE_2D_ARRAY, 0); continue; } qglActiveTexture(GL_TEXTURE0 + i); qglMatrixMode(GL_TEXTURE); qglLoadIdentity(); qglDisable(GL_TEXTURE_2D); qglDisable(GL_TEXTURE_3D); qglDisable(GL_TEXTURE_CUBE_MAP); qglDisable(GL_TEXTURE_2D_ARRAY); qglBindTexture(GL_TEXTURE_2D, 0); qglBindTexture(GL_TEXTURE_3D, 0); qglBindTexture(GL_TEXTURE_CUBE_MAP, 0); qglBindTexture(GL_TEXTURE_2D_ARRAY, 0); qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); qglDisable(GL_TEXTURE_GEN_S); qglDisable(GL_TEXTURE_GEN_T); qglDisable(GL_TEXTURE_GEN_R); qglDisable(GL_TEXTURE_GEN_Q); qglTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); qglTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); qglTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); qglTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); } qglDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); qglUseProgram(0); qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); qglBindBuffer(GL_ARRAY_BUFFER, 0); qglViewport(0, 0, glConfig.videoWidth, glConfig.videoHeight); qglEnable(GL_SCISSOR_TEST); qglScissor(0, 0, glConfig.videoWidth, glConfig.videoHeight); qglEnable(GL_DEPTH_BOUNDS_TEST_EXT); qglDepthBoundsEXT(0.0f, 1.0f); qglFrontFace(GL_CCW); qglShadeModel(GL_SMOOTH); qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL); qglDisable(GL_CULL_FACE); qglCullFace(GL_FRONT); qglDisable(GL_POLYGON_OFFSET_FILL); qglDisable(GL_POLYGON_OFFSET_LINE); qglPolygonOffset(0.0f, 0.0f); qglDisable(GL_BLEND); qglBlendFunc(GL_ONE, GL_ZERO); qglBlendEquation(GL_FUNC_ADD); qglDisable(GL_ALPHA_TEST); qglAlphaFunc(GL_GREATER, 0.0f); qglDisable(GL_DEPTH_TEST); qglDepthFunc(GL_LEQUAL); qglDisable(GL_STENCIL_TEST); qglStencilFunc(GL_ALWAYS, 128, 255); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); qglDepthRange(0.0f, 1.0f); qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); qglDepthMask(GL_TRUE); qglStencilMask(255); qglDisable(GL_DEPTH_CLAMP); qglDisable(GL_CLIP_PLANE0); if (glConfig.multiSamples > 1){ qglDisable(GL_MULTISAMPLE); qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); } qglClearColor(0.0f, 0.0f, 0.0f, 1.0f); qglClearDepth(1.0f); qglClearStencil(128); qglEnableClientState(GL_VERTEX_ARRAY); qglDisableVertexAttribArray(GL_ATTRIB_NORMAL); qglDisableVertexAttribArray(GL_ATTRIB_TANGENT1); qglDisableVertexAttribArray(GL_ATTRIB_TANGENT2); qglDisableVertexAttribArray(GL_ATTRIB_TEXCOORD); qglDisableVertexAttribArray(GL_ATTRIB_COLOR); QGL_LogPrintf("--------------------\n"); }
void GL_BindNullProgram() { qglUseProgram(0); glDsaState.program = 0; }