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 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 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 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(); } }