void fhImmediateMode::End() { active = false; if (!drawVertsUsed) return; auto vert = vertexCache.AllocFrameTemp(drawVerts, drawVertsUsed * sizeof(fhSimpleVert)); drawCallVertexSize += drawVertsUsed * sizeof(fhSimpleVert); int offset = vertexCache.Bind(vert); if (!geometryOnly) { if (currentTexture) { currentTexture->Bind(1); if (currentTexture->type == TT_CUBIC) { GL_UseProgram(skyboxProgram); } else if (currentTexture->internalFormat == GL_DEPTH_COMPONENT) { GL_UseProgram(debugDepthProgram); } else { GL_UseProgram(defaultProgram); } } else { GL_UseProgram(vertexColorProgram); } fhRenderProgram::SetModelViewMatrix(GL_ModelViewMatrix.Top()); fhRenderProgram::SetProjectionMatrix(GL_ProjectionMatrix.Top()); fhRenderProgram::SetDiffuseColor(idVec4::one); fhRenderProgram::SetColorAdd(idVec4::zero); fhRenderProgram::SetColorModulate(idVec4::one); fhRenderProgram::SetBumpMatrix(idVec4(1,0,0,0), idVec4(0,1,0,0)); } GL_SetupVertexAttributes(fhVertexLayout::Simple, offset); GLenum mode = currentMode; if (mode == GL_QUADS || mode == GL_POLYGON || mode == GL_QUAD_STRIP) //quads and polygons are replaced by triangles in GLSL mode mode = GL_TRIANGLES; glDrawElements(mode, drawVertsUsed, GL_UNSIGNED_SHORT, lineIndices); drawCallCount++; GL_SetVertexLayout(fhVertexLayout::None); if (!geometryOnly) { GL_UseProgram(nullptr); } drawVertsUsed = 0; currentMode = GL_INVALID_ENUM; }
void fhPointBuffer::entry_t::Commit() { const int verticesUsed = vertices.Num(); if (verticesUsed > 0) { glPointSize(size); GL_UseProgram(vertexColorProgram); fhRenderProgram::SetModelViewMatrix(GL_ModelViewMatrix.Top()); fhRenderProgram::SetProjectionMatrix(GL_ProjectionMatrix.Top()); fhRenderProgram::SetDiffuseColor(idVec4(1,1,1,1)); fhRenderProgram::SetColorAdd(idVec4(0,0,0,0)); fhRenderProgram::SetColorModulate(idVec4(1,1,1,1)); int verticesCommitted = 0; while (verticesCommitted < verticesUsed) { int verticesToCommit = std::min(maxVerticesPerCommit, verticesUsed - verticesCommitted); auto vert = vertexCache.AllocFrameTemp(&vertices[verticesCommitted], verticesToCommit * sizeof(fhSimpleVert)); int offset = vertexCache.Bind(vert); GL_SetupVertexAttributes(fhVertexLayout::DrawPosColorOnly, offset); glDrawElements(GL_POINTS, verticesToCommit, GL_UNSIGNED_SHORT, ::indices()); verticesCommitted += verticesToCommit; } glPointSize(1); } }
void Pass2D::setup(GLRenderer *r) { Pass::setup(r); GL_Enable(GL_SCISSOR_TEST); GL_Disable(GL_LIGHTING); GL_Disable(GL_DEPTH_TEST); GL_Disable(GL_CULL_FACE); GL_Enable(GL_BLEND); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glAlphaFunc(GL_GREATER, 0.01f); Cvar_SetVarValue(&gfx_GLSLPass, 0); GL_TexModulate(1.0); GL_UseProgram(0); GL_MatrixMode(GL_PROJECTION); GL_PushMatrix(); glLoadIdentity(); glOrtho(0, Vid_GetScreenW(), Vid_GetScreenH(), 0, -1.0, 1.0); GL_MatrixMode(GL_MODELVIEW); GL_PushMatrix(); glLoadIdentity(); #ifdef DEBUG GLSL_catchLastError("Pass2D::setup(): "); #endif }
GLvoid APIENTRY GLDSA_ProgramUniformMatrix4fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { GL_UseProgram(program); qglUniformMatrix4fv(location, count, transpose, value); }
void R_DrawSkyChain (msurface_t *surf) { msurface_t *reversechain = NULL; int numindexes = 0; if (!surf) return; // push the depth range back to far end of the z-buffer // rogue has some pretty - unusual - brush placement and needs this glDepthRange (gldepthmax, gldepthmax); glProgramUniformMatrix4fv (gl_skycubeprog, u_skylocalMatrix, 1, GL_FALSE, r_mvpmatrix.m[0]); glEnable (GL_TEXTURE_CUBE_MAP_SEAMLESS); GL_UseProgram (gl_skycubeprog); GL_BindTexture (GL_TEXTURE0, GL_TEXTURE_CUBE_MAP, r_skysampler, r_skytexture); GL_Enable (DEPTHTEST_BIT | (gl_cull->value ? CULLFACE_BIT : 0)); for (; surf; surf = surf->texturechain) { surf->reversechain = reversechain; reversechain = surf; numindexes += surf->numindexes; } R_DrawSurfaceChain (reversechain, numindexes); glDepthRange (gldepthmin, gldepthmax); glDisable (GL_TEXTURE_CUBE_MAP_SEAMLESS); }
void fhTrisBuffer::Commit(idImage* texture, const idVec4& colorModulate, const idVec4& colorAdd) { const int verticesUsed = vertices.Num(); if (verticesUsed > 0) { if (texture) { texture->Bind(1); if (texture->type == TT_CUBIC) GL_UseProgram(skyboxProgram); else GL_UseProgram(defaultProgram); } else { GL_UseProgram(vertexColorProgram); } fhRenderProgram::SetModelViewMatrix(GL_ModelViewMatrix.Top()); fhRenderProgram::SetProjectionMatrix(GL_ProjectionMatrix.Top()); fhRenderProgram::SetDiffuseColor(idVec4(1,1,1,1)); fhRenderProgram::SetColorAdd(colorAdd); fhRenderProgram::SetColorModulate(colorModulate); fhRenderProgram::SetBumpMatrix(idVec4(1,0,0,0), idVec4(0,1,0,0)); int verticesCommitted = 0; while (verticesCommitted < verticesUsed) { int verticesToCommit = std::min(maxVerticesPerCommit, verticesUsed - verticesCommitted); auto vert = vertexCache.AllocFrameTemp(&vertices[verticesCommitted], verticesToCommit * sizeof(fhSimpleVert)); int offset = vertexCache.Bind(vert); GL_SetupVertexAttributes(fhVertexLayout::Simple, offset); glDrawElements(GL_TRIANGLES, verticesToCommit, GL_UNSIGNED_SHORT, indices()); verticesCommitted += verticesToCommit; } } }
void DepthNormalPass::finalize() { Cvar_SetVarValue(&gfx_GLSLPass, 1); Cvar_SetVarValue(&gfx_clouds, saveClouds); Cvar_SetVarValue(&gfx_grass, saveGrass); Cvar_SetVarValue(&gfx_sky, 1); GL_UseProgram(0); GL_Enable(GL_LIGHTING); GL_Enable(GL_BLEND); Pass::finalize(); GLSL_catchLastError("DepthNormalPass::finalize(): "); }
void fhLineBuffer::Commit() { if(verticesUsed > 0) { GL_UseProgram(vertexColorProgram); fhRenderProgram::SetModelViewMatrix(GL_ModelViewMatrix.Top()); fhRenderProgram::SetProjectionMatrix(GL_ProjectionMatrix.Top()); fhRenderProgram::SetDiffuseColor(idVec4::one); fhRenderProgram::SetColorAdd(idVec4::zero); fhRenderProgram::SetColorModulate(idVec4::one); fhRenderProgram::SetBumpMatrix(idVec4(1,0,0,0), idVec4(0,1,0,0)); int verticesCommitted = 0; while(verticesCommitted < verticesUsed) { static const int maxVerticesPerCommit = (sizeof(lineIndices)/sizeof(lineIndices[0]))/2; int verticesToCommit = Min(maxVerticesPerCommit, verticesUsed - verticesCommitted); auto vert = vertexCache.AllocFrameTemp(&vertices[verticesCommitted], verticesToCommit * sizeof(fhSimpleVert)); int offset = vertexCache.Bind(vert); GL_SetupVertexAttributes(fhVertexLayout::Simple, offset); glDrawElements(GL_LINES, verticesToCommit, GL_UNSIGNED_SHORT, lineIndices); verticesCommitted += verticesToCommit; } } verticesUsed = 0; }
void fhImmediateMode::Sphere(float radius, int rings, int sectors, bool inverse) { assert(!active); assert(radius > 0.0f); assert(rings > 1); assert(sectors > 1); float const R = 1. / (float)(rings - 1); float const S = 1. / (float)(sectors - 1); int vertexNum = 0; for (int r = 0; r < rings; r++) { for (int s = 0; s < sectors; s++) { float const y = sin(-(idMath::PI/2.0f) + idMath::PI * r * R); float const x = cos(2 * idMath::PI * s * S) * sin(idMath::PI * r * R); float const z = sin(2 * idMath::PI * s * S) * sin(idMath::PI * r * R); drawVerts[vertexNum].xyz.x = x * radius; drawVerts[vertexNum].xyz.y = y * radius; drawVerts[vertexNum].xyz.z = z * radius; drawVerts[vertexNum].st.x = s*S; drawVerts[vertexNum].st.y = r*R; drawVerts[vertexNum].color[0] = currentColor[0]; drawVerts[vertexNum].color[1] = currentColor[1]; drawVerts[vertexNum].color[2] = currentColor[2]; drawVerts[vertexNum].color[3] = currentColor[3]; vertexNum += 1; } } int indexNum = 0; for (int r = 0; r < rings - 1; r++) { for (int s = 0; s < sectors - 1; s++) { if(r == 0) { //faces of first ring are single triangles sphereIndices[indexNum + 2] = r * sectors + s; sphereIndices[indexNum + 1] = (r + 1) * sectors + s; sphereIndices[indexNum + 0] = (r + 1) * sectors + (s + 1); indexNum += 3; } else if (r == rings - 2) { //faces of last ring are single triangles sphereIndices[indexNum + 0] = r * sectors + s; sphereIndices[indexNum + 1] = r * sectors + (s + 1); sphereIndices[indexNum + 2] = (r + 1) * sectors + (s + 1); indexNum += 3; } else { //faces of remaining rings are quads (two triangles) sphereIndices[indexNum + 0] = r * sectors + s; sphereIndices[indexNum + 1] = r * sectors + (s + 1); sphereIndices[indexNum + 2] = (r + 1) * sectors + (s + 1); sphereIndices[indexNum + 3] = sphereIndices[indexNum + 2]; sphereIndices[indexNum + 4] = (r + 1) * sectors + s; sphereIndices[indexNum + 5] = sphereIndices[indexNum + 0]; indexNum += 6; } } } if(inverse) { for(int i = 0; i+2 < indexNum; i += 3) { unsigned short tmp = sphereIndices[i]; sphereIndices[i] = sphereIndices[i+2]; sphereIndices[i+2] = tmp; } } GL_UseProgram(vertexColorProgram); auto vert = vertexCache.AllocFrameTemp(drawVerts, vertexNum * sizeof(fhSimpleVert)); int offset = vertexCache.Bind(vert); fhRenderProgram::SetModelViewMatrix(GL_ModelViewMatrix.Top()); fhRenderProgram::SetProjectionMatrix(GL_ProjectionMatrix.Top()); fhRenderProgram::SetDiffuseColor(idVec4::one); fhRenderProgram::SetBumpMatrix(idVec4(1,0,0,0), idVec4(0,1,0,0)); GL_SetupVertexAttributes(fhVertexLayout::Simple, offset); glDrawElements(GL_TRIANGLES, indexNum, GL_UNSIGNED_SHORT, sphereIndices); GL_SetVertexLayout(fhVertexLayout::None); GL_UseProgram(nullptr); }
static void RB_GLSL_SubmitDrawInteractions(const viewLight_t& vLight, const InteractionList& interactionList) { if (interactionList.IsEmpty()) return; // perform setup here that will be constant for all interactions GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | backEnd.depthFunc ); GL_UseProgram( interactionProgram ); fhRenderProgram::SetShading( r_shading.GetInteger() ); fhRenderProgram::SetSpecularExp( r_specularExp.GetFloat() ); fhRenderProgram::SetAmbientLight( vLight.lightDef->lightShader->IsAmbientLight() ? 1 : 0 ); if (vLight.lightDef->ShadowMode() == shadowMode_t::ShadowMap) { const idVec4 globalLightOrigin = idVec4( vLight.globalLightOrigin, 1 ); fhRenderProgram::SetGlobalLightOrigin( globalLightOrigin ); const float shadowBrightness = vLight.lightDef->ShadowBrightness(); const float shadowSoftness = vLight.lightDef->ShadowSoftness(); fhRenderProgram::SetShadowParams( idVec4( shadowSoftness, shadowBrightness, vLight.nearClip[0], vLight.farClip[0] ) ); if(vLight.lightDef->parms.parallel) { //parallel light fhRenderProgram::SetShadowMappingMode( 3 ); fhRenderProgram::SetPointLightProjectionMatrices( vLight.viewProjectionMatrices[0].ToFloatPtr() ); fhRenderProgram::SetShadowCoords( vLight.shadowCoords, 6 ); fhRenderProgram::SetCascadeDistances( r_smCascadeDistance0.GetFloat(), r_smCascadeDistance1.GetFloat(), r_smCascadeDistance2.GetFloat(), r_smCascadeDistance3.GetFloat(), r_smCascadeDistance4.GetFloat()); idVec4 shadowmapSizes[6] = { idVec4(vLight.nearClip[0], vLight.farClip[0], vLight.width[0], vLight.height[0]), idVec4(vLight.nearClip[1], vLight.farClip[1], vLight.width[1], vLight.height[1]), idVec4(vLight.nearClip[2], vLight.farClip[2], vLight.width[2], vLight.height[2]), idVec4(vLight.nearClip[3], vLight.farClip[3], vLight.width[3], vLight.height[3]), idVec4(vLight.nearClip[4], vLight.farClip[4], vLight.width[4], vLight.height[4]), idVec4(vLight.nearClip[5], vLight.farClip[5], vLight.width[5], vLight.height[5]) }; fhRenderProgram::SetShadowMapSize(shadowmapSizes, 6); } else if (vLight.lightDef->parms.pointLight) { //point light fhRenderProgram::SetShadowMappingMode( 1 ); fhRenderProgram::SetPointLightProjectionMatrices( vLight.viewProjectionMatrices[0].ToFloatPtr() ); fhRenderProgram::SetShadowCoords(vLight.shadowCoords, 6); { const idMat3 axis = vLight.lightDef->parms.axis; float viewerMatrix[16]; viewerMatrix[0] = axis[0][0]; viewerMatrix[4] = axis[0][1]; viewerMatrix[8] = axis[0][2]; viewerMatrix[12] = 0; viewerMatrix[1] = axis[1][0]; viewerMatrix[5] = axis[1][1]; viewerMatrix[9] = axis[1][2]; viewerMatrix[13] = 0; viewerMatrix[2] = axis[2][0]; viewerMatrix[6] = axis[2][1]; viewerMatrix[10] = axis[2][2]; viewerMatrix[14] = 0; viewerMatrix[3] = 0; viewerMatrix[7] = 0; viewerMatrix[11] = 0; viewerMatrix[15] = 1; fhRenderProgram::SetInverseLightRotation( viewerMatrix ); } } else { //projected light fhRenderProgram::SetShadowMappingMode( 2 ); fhRenderProgram::SetSpotLightProjectionMatrix( vLight.viewProjectionMatrices[0].ToFloatPtr() ); fhRenderProgram::SetShadowCoords(vLight.shadowCoords, 1); } } else { //no shadows fhRenderProgram::SetShadowMappingMode( 0 ); } //make sure depth hacks are disabled //FIXME(johl): why is (sometimes) a depth hack enabled at this point? RB_LeaveDepthHack(); fhRenderProgram::SetProjectionMatrix( backEnd.viewDef->projectionMatrix ); fhRenderProgram::SetPomMaxHeight( -1 ); const viewEntity_t* currentSpace = nullptr; stageVertexColor_t currentVertexColor = (stageVertexColor_t)-1; bool currentPomEnabled = false; idScreenRect currentScissor; bool depthHackActive = false; bool currentHasBumpMatrix = false; bool currentHasDiffuseMatrix = false; bool currentHasSpecularMatrix = false; idVec4 currentDiffuseColor = idVec4( 1, 1, 1, 1 ); idVec4 currentSpecularColor = idVec4( 1, 1, 1, 1 ); fhRenderProgram::SetDiffuseColor( currentDiffuseColor ); fhRenderProgram::SetSpecularColor( currentSpecularColor ); fhRenderProgram::SetBumpMatrix( idVec4::identityS, idVec4::identityT ); fhRenderProgram::SetSpecularMatrix( idVec4::identityS, idVec4::identityT ); fhRenderProgram::SetDiffuseMatrix( idVec4::identityS, idVec4::identityT ); glDepthRange(0, 1); if (r_useScissor.GetBool()) { auto fb = fhFramebuffer::GetCurrentDrawBuffer(); glScissor( 0, 0, fb->GetWidth(), fb->GetHeight() ); currentScissor.x1 = 0; currentScissor.y1 = 0; currentScissor.x2 = fb->GetWidth(); currentScissor.y2 = fb->GetHeight(); } const int num = interactionList.Num(); for (int i = 0; i < num; ++i) { const auto& din = interactionList[i]; const auto offset = vertexCache.Bind( din.surf->geo->ambientCache ); GL_SetupVertexAttributes( fhVertexLayout::Draw, offset ); if (currentSpace != din.surf->space) { fhRenderProgram::SetModelMatrix( din.surf->space->modelMatrix ); fhRenderProgram::SetModelViewMatrix( din.surf->space->modelViewMatrix ); if (din.surf->space->modelDepthHack) { RB_EnterModelDepthHack( din.surf->space->modelDepthHack ); fhRenderProgram::SetProjectionMatrix( GL_ProjectionMatrix.Top() ); depthHackActive = true; } else if (din.surf->space->weaponDepthHack) { RB_EnterWeaponDepthHack(); fhRenderProgram::SetProjectionMatrix( GL_ProjectionMatrix.Top() ); depthHackActive = true; } else if (depthHackActive) { RB_LeaveDepthHack(); fhRenderProgram::SetProjectionMatrix( GL_ProjectionMatrix.Top() ); depthHackActive = false; } // change the scissor if needed if (r_useScissor.GetBool() && !currentScissor.Equals( din.surf->scissorRect )) { currentScissor = din.surf->scissorRect; glScissor( backEnd.viewDef->viewport.x1 + currentScissor.x1, backEnd.viewDef->viewport.y1 + currentScissor.y1, currentScissor.x2 + 1 - currentScissor.x1, currentScissor.y2 + 1 - currentScissor.y1 ); } currentSpace = din.surf->space; } fhRenderProgram::SetLocalLightOrigin( din.localLightOrigin ); fhRenderProgram::SetLocalViewOrigin( din.localViewOrigin ); fhRenderProgram::SetLightProjectionMatrix( din.lightProjection[0], din.lightProjection[1], din.lightProjection[2] ); fhRenderProgram::SetLightFallOff( din.lightProjection[3] ); if (din.hasBumpMatrix) { fhRenderProgram::SetBumpMatrix( din.bumpMatrix[0], din.bumpMatrix[1] ); currentHasBumpMatrix = true; } else if (currentHasBumpMatrix) { fhRenderProgram::SetBumpMatrix( idVec4::identityS, idVec4::identityT ); currentHasBumpMatrix = false; } if (din.hasDiffuseMatrix) { fhRenderProgram::SetDiffuseMatrix( din.diffuseMatrix[0], din.diffuseMatrix[1] ); currentHasDiffuseMatrix = true; } else if (currentHasDiffuseMatrix) { fhRenderProgram::SetDiffuseMatrix( idVec4::identityS, idVec4::identityT ); currentHasDiffuseMatrix = false; } if (din.hasSpecularMatrix) { fhRenderProgram::SetSpecularMatrix( din.specularMatrix[0], din.specularMatrix[1] ); currentHasSpecularMatrix = true; } else if (currentHasSpecularMatrix) { fhRenderProgram::SetSpecularMatrix( idVec4::identityS, idVec4::identityT ); currentHasSpecularMatrix = false; } if (currentVertexColor != din.vertexColor) { switch (din.vertexColor) { case SVC_IGNORE: fhRenderProgram::SetColorModulate( idVec4::zero ); fhRenderProgram::SetColorAdd( idVec4::one ); break; case SVC_MODULATE: fhRenderProgram::SetColorModulate( idVec4::one ); fhRenderProgram::SetColorAdd( idVec4::zero ); break; case SVC_INVERSE_MODULATE: fhRenderProgram::SetColorModulate( idVec4::negOne ); fhRenderProgram::SetColorAdd( idVec4::one ); break; } currentVertexColor = din.vertexColor; } if (din.diffuseColor != currentDiffuseColor) { fhRenderProgram::SetDiffuseColor( din.diffuseColor ); currentDiffuseColor = din.diffuseColor; } if (din.specularColor != currentSpecularColor) { fhRenderProgram::SetSpecularColor( din.specularColor ); currentSpecularColor = din.specularColor; } const bool pomEnabled = r_pomEnabled.GetBool() && din.specularImage->hasAlpha; if (pomEnabled != currentPomEnabled) { if (pomEnabled) { fhRenderProgram::SetPomMaxHeight( r_pomMaxHeight.GetFloat() ); } else { fhRenderProgram::SetPomMaxHeight( -1 ); } } fhRenderProgram::SetNormalMapEncoding( RB_GetNormalEncoding( din.bumpImage ) ); din.bumpImage->Bind( 1 ); din.lightFalloffImage->Bind( 2 ); din.lightImage->Bind( 3 ); din.diffuseImage->Bind( 4 ); din.specularImage->Bind( 5 ); // draw it backEnd.stats.groups[backEndGroup::Interaction].drawcalls += 1; backEnd.stats.groups[backEndGroup::Interaction].tris += din.surf->geo->numIndexes / 3; RB_DrawElementsWithCounters( din.surf->geo ); } if (depthHackActive) { RB_LeaveDepthHack(); fhRenderProgram::SetProjectionMatrix( GL_ProjectionMatrix.Top() ); } if (r_useScissor.GetBool()) { auto fb = fhFramebuffer::GetCurrentDrawBuffer(); glScissor( 0, 0, fb->GetWidth(), fb->GetHeight() ); backEnd.currentScissor.x1 = 0; backEnd.currentScissor.y1 = 0; backEnd.currentScissor.x2 = fb->GetWidth(); backEnd.currentScissor.y2 = fb->GetHeight(); } }
GLvoid APIENTRY GLDSA_ProgramUniform1fvEXT(GLuint program, GLint location, GLsizei count, const GLfloat *value) { GL_UseProgram(program); qglUniform1fv(location, count, value); }
GLvoid APIENTRY GLDSA_ProgramUniform4fEXT(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) { GL_UseProgram(program); qglUniform4f(location, v0, v1, v2, v3); }
GLvoid APIENTRY GLDSA_ProgramUniform2fEXT(GLuint program, GLint location, GLfloat v0, GLfloat v1) { GL_UseProgram(program); qglUniform2f(location, v0, v1); }
GLvoid APIENTRY GLDSA_ProgramUniform1iEXT(GLuint program, GLint location, GLint v0) { GL_UseProgram(program); qglUniform1i(location, v0); }
/* ================= R_DrawDecals Draws all decals on the decal list ================= */ void R_DrawDecals (void) { cdecal_t *dl, *next, *active; float mindist, time; int r_numdecals = 0; vec3_t v; vec4_t color; if (!gl_decals->value) return; if (r_newrefdef.rdflags & RDF_NOWORLDMODEL) return; active = &active_decals; mindist = DotProduct(r_origin, vpn) + 4.0; glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-2, -2); GL_Enable(BLEND_BIT | DEPTHTEST_BIT); GL_UseProgram(gl_decalprog); glProgramUniformMatrix4fv (gl_decalprog, gl_decalmvpMatrix, 1, GL_FALSE, r_mvpmatrix.m[0]); for (dl = active->next; dl != active; dl = next) { next = dl->next; if (dl->node == NULL || dl->node->visframe != r_visframecount) continue; // check type if (dl->type < 0 || dl->type > MAX_DECAL_TEX) { R_FreeDecal (dl); continue; } // have we faded out yet? if (dl->time + gl_decalsTime->value <= r_newrefdef.time) { R_FreeDecal (dl); continue; } // do not render if the decal is behind the view if (DotProduct(dl->org, vpn) < mindist) continue; // do not render if the view origin is behind the decal VectorSubtract(dl->org, r_origin, v); if (DotProduct(dl->direction, v) < 0) continue; Vector4Copy(dl->color, color); time = dl->time + gl_decalsTime->value - r_newrefdef.time; if (time < 1.5) color[3] *= time / 1.5; // bind texture GL_BindTexture(GL_TEXTURE0, GL_TEXTURE_2D, r_drawnearestclampsampler, r_decalImages[dl->type]); // bind data into vbo glBindBuffer(GL_ARRAY_BUFFER, gl_decalvbo); glBufferData(GL_ARRAY_BUFFER, sizeof(dl->verts) + sizeof(dl->stcoords) + sizeof(color), NULL, GL_DYNAMIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(dl->verts), dl->verts); glBufferSubData(GL_ARRAY_BUFFER, sizeof(dl->verts), sizeof(dl->stcoords), dl->stcoords); glBufferSubData(GL_ARRAY_BUFFER, sizeof(dl->verts) + sizeof(dl->stcoords), sizeof(color), color); // bind vao GL_BindVertexArray(gl_decalvao); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void *)sizeof(dl->verts)); glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (void *)(sizeof(dl->verts) + sizeof(dl->stcoords))); // draw glDrawArrays(GL_TRIANGLE_FAN, 0, dl->numverts); r_numdecals++; if (r_numdecals >= MAX_DECALS) break; } glDisable(GL_POLYGON_OFFSET_FILL); }
/* ============= GL_DrawAliasFrameLerp interpolates between two frames and origins FIXME: batch lerp all vertexes ============= */ void GL_DrawAliasFrameLerp (entity_t *e, dmdl_t *hdr, float backlerp) { int i; float frontlerp; float alpha; vec3_t delta, vectors[3]; daliasframe_t *currframe = (daliasframe_t *) ((byte *) hdr + hdr->ofs_frames + e->currframe * hdr->framesize); daliasframe_t *lastframe = (daliasframe_t *) ((byte *) hdr + hdr->ofs_frames + e->lastframe * hdr->framesize); meshubo_t *meshubo = NULL; GLbitfield access; if (e->flags & RF_TRANSLUCENT) alpha = e->alpha; else alpha = 1.0; frontlerp = 1.0 - backlerp; // move should be the delta back to the previous frame * backlerp VectorSubtract (e->lastorigin, e->currorigin, delta); AngleVectors (e->angles, vectors[0], vectors[1], vectors[2]); gl_meshuboupdate.move[0] = lastframe->translate[0] + DotProduct (delta, vectors[0]); // forward gl_meshuboupdate.move[1] = lastframe->translate[1] - DotProduct (delta, vectors[1]); // left gl_meshuboupdate.move[2] = lastframe->translate[2] + DotProduct (delta, vectors[2]); // up for (i = 0; i < 3; i++) { gl_meshuboupdate.move[i] = backlerp * gl_meshuboupdate.move[i] + frontlerp * currframe->translate[i]; gl_meshuboupdate.frontv[i] = frontlerp * currframe->scale[i]; gl_meshuboupdate.backv[i] = backlerp * lastframe->scale[i]; } if (!(e->flags & (RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE))) { if (gl_monolightmap->value) { float ntsc[] = {0.3f, 0.59f, 0.11f}; float gs = DotProduct (gl_meshuboupdate.shadelight, ntsc); gl_meshuboupdate.shadelight[0] = gl_meshuboupdate.shadelight[1] = gl_meshuboupdate.shadelight[2] = gs; } gl_meshuboupdate.shadelight[0] *= r_lightscale->value * 2.0f; gl_meshuboupdate.shadelight[1] *= r_lightscale->value * 2.0f; gl_meshuboupdate.shadelight[2] *= r_lightscale->value * 2.0f; gl_meshuboupdate.powersuitscale = 0.0f; gl_meshuboupdate.shellmix = 0.0f; } else { float scale = (e->flags & RF_WEAPONMODEL) ? WEAPONSHELL_SCALE : POWERSUIT_SCALE; gl_meshuboupdate.powersuitscale = scale; gl_meshuboupdate.shellmix = 1.0f; } gl_meshuboupdate.shadelight[3] = alpha; gl_meshuboupdate.lerpfrac = backlerp; if (e->model->lastcurrframe != e->currframe) { glVertexArrayVertexAttribOffsetEXT (e->model->meshvao, e->model->meshvbo, 0, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof (posevert_t), VERTOFFSET (e->currframe)); e->model->lastcurrframe = e->currframe; } if (e->model->lastlastframe != e->lastframe) { glVertexArrayVertexAttribOffsetEXT (e->model->meshvao, e->model->meshvbo, 1, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof (posevert_t), VERTOFFSET (e->lastframe)); e->model->lastlastframe = e->lastframe; } GL_BindVertexArray (e->model->meshvao); GL_Enable (DEPTHTEST_BIT | ((e->flags & RF_TRANSLUCENT) ? BLEND_BIT : DEPTHWRITE_BIT) | (gl_cull->value ? CULLFACE_BIT : 0)); GL_UseProgram (gl_meshprog); if (gl_meshubonumblocks + 1 >= MESH_UBO_MAX_BLOCKS) { access = BUFFER_DISCARD; gl_meshubonumblocks = 0; } else access = BUFFER_NO_OVERWRITE; if ((meshubo = glMapNamedBufferRangeEXT (gl_meshubo, gl_meshubonumblocks * gl_meshuboblocksize, sizeof (meshubo_t), access)) != NULL) { memcpy (meshubo, &gl_meshuboupdate, sizeof (meshubo_t)); glUnmapNamedBufferEXT (gl_meshubo); glBindBufferRange (GL_UNIFORM_BUFFER, gl_meshubobinding, gl_meshubo, gl_meshubonumblocks * gl_meshuboblocksize, sizeof (meshubo_t)); glDrawElements (GL_TRIANGLES, e->model->numindexes, GL_UNSIGNED_SHORT, NULL); gl_meshubonumblocks++; } }