/* ============== RB_InstantQuad based on Tess_InstantQuad from xreal ============== */ void RB_InstantQuad2(vec4_t quadVerts[4], vec2_t texCoords[4]) { GLimp_LogComment("--- RB_InstantQuad2 ---\n"); tess.numVertexes = 0; tess.numIndexes = 0; tess.firstIndex = 0; VectorCopy4(quadVerts[0], tess.xyz[tess.numVertexes]); VectorCopy2(texCoords[0], tess.texCoords[tess.numVertexes]); tess.numVertexes++; VectorCopy4(quadVerts[1], tess.xyz[tess.numVertexes]); VectorCopy2(texCoords[1], tess.texCoords[tess.numVertexes]); tess.numVertexes++; VectorCopy4(quadVerts[2], tess.xyz[tess.numVertexes]); VectorCopy2(texCoords[2], tess.texCoords[tess.numVertexes]); tess.numVertexes++; VectorCopy4(quadVerts[3], tess.xyz[tess.numVertexes]); VectorCopy2(texCoords[3], tess.texCoords[tess.numVertexes]); tess.numVertexes++; tess.indexes[tess.numIndexes++] = 0; tess.indexes[tess.numIndexes++] = 1; tess.indexes[tess.numIndexes++] = 2; tess.indexes[tess.numIndexes++] = 0; tess.indexes[tess.numIndexes++] = 2; tess.indexes[tess.numIndexes++] = 3; tess.minIndex = 0; tess.maxIndex = 3; RB_UpdateTessVao(ATTR_POSITION | ATTR_TEXCOORD); R_DrawElementsVao(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); tess.numIndexes = 0; tess.numVertexes = 0; tess.firstIndex = 0; tess.minIndex = 0; tess.maxIndex = 0; }
void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexScale, FBO_t *dst, ivec4_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend) { ivec4_t dstBox, srcBox; vec2_t srcTexScale; vec4_t color; vec4_t quadVerts[4]; vec2_t texCoords[4]; vec2_t invTexRes; FBO_t *oldFbo = glState.currentFBO; mat4_t projection; int width, height; if (!src) return; if (inSrcBox) { VectorSet4(srcBox, inSrcBox[0], inSrcBox[1], inSrcBox[0] + inSrcBox[2], inSrcBox[1] + inSrcBox[3]); } else { VectorSet4(srcBox, 0, 0, src->width, src->height); } // framebuffers are 0 bottom, Y up. if (inDstBox) { if (dst) { dstBox[0] = inDstBox[0]; dstBox[1] = dst->height - inDstBox[1] - inDstBox[3]; dstBox[2] = inDstBox[0] + inDstBox[2]; dstBox[3] = dst->height - inDstBox[1]; } else { dstBox[0] = inDstBox[0]; dstBox[1] = glConfig.vidHeight - inDstBox[1] - inDstBox[3]; dstBox[2] = inDstBox[0] + inDstBox[2]; dstBox[3] = glConfig.vidHeight - inDstBox[1]; } } else if (dst) { VectorSet4(dstBox, 0, dst->height, dst->width, 0); } else { VectorSet4(dstBox, 0, glConfig.vidHeight, glConfig.vidWidth, 0); } if (inSrcTexScale) { VectorCopy2(inSrcTexScale, srcTexScale); } else { srcTexScale[0] = srcTexScale[1] = 1.0f; } if (inColor) { VectorCopy4(inColor, color); } else { VectorCopy4(colorWhite, color); } if (!shaderProgram) { shaderProgram = &tr.textureColorShader; } FBO_Bind(dst); if (glState.currentFBO) { width = glState.currentFBO->width; height = glState.currentFBO->height; } else { width = glConfig.vidWidth; height = glConfig.vidHeight; } qglViewport( 0, 0, width, height ); qglScissor( 0, 0, width, height ); Mat4Ortho(0, width, height, 0, 0, 1, projection); qglDisable( GL_CULL_FACE ); GL_BindToTMU(src, TB_COLORMAP); VectorSet4(quadVerts[0], dstBox[0], dstBox[1], 0, 1); VectorSet4(quadVerts[1], dstBox[2], dstBox[1], 0, 1); VectorSet4(quadVerts[2], dstBox[2], dstBox[3], 0, 1); VectorSet4(quadVerts[3], dstBox[0], dstBox[3], 0, 1); texCoords[0][0] = srcBox[0] / (float)src->width; texCoords[0][1] = 1.0f - srcBox[1] / (float)src->height; texCoords[1][0] = srcBox[2] / (float)src->width; texCoords[1][1] = 1.0f - srcBox[1] / (float)src->height; texCoords[2][0] = srcBox[2] / (float)src->width; texCoords[2][1] = 1.0f - srcBox[3] / (float)src->height; texCoords[3][0] = srcBox[0] / (float)src->width; texCoords[3][1] = 1.0f - srcBox[3] / (float)src->height; invTexRes[0] = 1.0f / src->width * srcTexScale[0]; invTexRes[1] = 1.0f / src->height * srcTexScale[1]; GL_State( blend ); GLSL_BindProgram(shaderProgram); GLSL_SetUniformMat4(shaderProgram, UNIFORM_MODELVIEWPROJECTIONMATRIX, projection); GLSL_SetUniformVec4(shaderProgram, UNIFORM_COLOR, color); GLSL_SetUniformVec2(shaderProgram, UNIFORM_INVTEXRES, invTexRes); GLSL_SetUniformVec2(shaderProgram, UNIFORM_AUTOEXPOSUREMINMAX, tr.refdef.autoExposureMinMax); GLSL_SetUniformVec3(shaderProgram, UNIFORM_TONEMINAVGMAXLINEAR, tr.refdef.toneMinAvgMaxLinear); RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); FBO_Bind(oldFbo); }
void FBO_BlitFromTexture(struct image_s *src, vec4_t inSrcTexCorners, vec2_t inSrcTexScale, FBO_t *dst, ivec4_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend) { ivec4_t dstBox; vec4_t color; vec4_t quadVerts[4]; vec2_t texCoords[4]; vec2_t invTexRes; FBO_t *oldFbo = glState.currentFBO; mat4_t projection; int width, height; if (!src) { ri.Printf(PRINT_WARNING, "Tried to blit from a NULL texture!\n"); return; } width = dst ? dst->width : glConfig.vidWidth; height = dst ? dst->height : glConfig.vidHeight; if (inSrcTexCorners) { VectorSet2(texCoords[0], inSrcTexCorners[0], inSrcTexCorners[1]); VectorSet2(texCoords[1], inSrcTexCorners[2], inSrcTexCorners[1]); VectorSet2(texCoords[2], inSrcTexCorners[2], inSrcTexCorners[3]); VectorSet2(texCoords[3], inSrcTexCorners[0], inSrcTexCorners[3]); } else { VectorSet2(texCoords[0], 0.0f, 1.0f); VectorSet2(texCoords[1], 1.0f, 1.0f); VectorSet2(texCoords[2], 1.0f, 0.0f); VectorSet2(texCoords[3], 0.0f, 0.0f); } // framebuffers are 0 bottom, Y up. if (inDstBox) { dstBox[0] = inDstBox[0]; dstBox[1] = height - inDstBox[1] - inDstBox[3]; dstBox[2] = inDstBox[0] + inDstBox[2]; dstBox[3] = height - inDstBox[1]; } else { VectorSet4(dstBox, 0, height, width, 0); } if (inSrcTexScale) { VectorCopy2(inSrcTexScale, invTexRes); } else { VectorSet2(invTexRes, 1.0f, 1.0f); } if (inColor) { VectorCopy4(inColor, color); } else { VectorCopy4(colorWhite, color); } if (!shaderProgram) { shaderProgram = &tr.textureColorShader; } FBO_Bind(dst); qglViewport( 0, 0, width, height ); qglScissor( 0, 0, width, height ); Mat4Ortho(0, width, height, 0, 0, 1, projection); GL_Cull( CT_TWO_SIDED ); GL_BindToTMU(src, TB_COLORMAP); VectorSet4(quadVerts[0], dstBox[0], dstBox[1], 0.0f, 1.0f); VectorSet4(quadVerts[1], dstBox[2], dstBox[1], 0.0f, 1.0f); VectorSet4(quadVerts[2], dstBox[2], dstBox[3], 0.0f, 1.0f); VectorSet4(quadVerts[3], dstBox[0], dstBox[3], 0.0f, 1.0f); invTexRes[0] /= src->width; invTexRes[1] /= src->height; GL_State( blend ); GLSL_BindProgram(shaderProgram); GLSL_SetUniformMat4(shaderProgram, UNIFORM_MODELVIEWPROJECTIONMATRIX, projection); GLSL_SetUniformVec4(shaderProgram, UNIFORM_COLOR, color); GLSL_SetUniformVec2(shaderProgram, UNIFORM_INVTEXRES, invTexRes); GLSL_SetUniformVec2(shaderProgram, UNIFORM_AUTOEXPOSUREMINMAX, tr.refdef.autoExposureMinMax); GLSL_SetUniformVec3(shaderProgram, UNIFORM_TONEMINAVGMAXLINEAR, tr.refdef.toneMinAvgMaxLinear); RB_InstantQuad2(quadVerts, texCoords); FBO_Bind(oldFbo); }
//------------------------- // FX_AddPoly //------------------------- CPoly *FX_AddPoly( vec3_t *verts, vec2_t *st, int numVerts, vec3_t vel, vec3_t accel, float alpha1, float alpha2, float alphaParm, vec3_t rgb1, vec3_t rgb2, float rgbParm, vec3_t rotationDelta, float bounce, int motionDelay, int killTime, qhandle_t shader, int flags ) { if ( theFxHelper.mFrameTime < 1 || !verts ) { // disallow adding effects when the system is paused or the user doesn't pass in a vert array return 0; } CPoly *fx = new CPoly; if ( fx ) { // Do a cheesy copy of the verts and texture coords into our own structure for ( int i = 0; i < numVerts; i++ ) { VectorCopy( verts[i], fx->mOrg[i] ); VectorCopy2( st[i], fx->mST[i] ); } fx->SetVel( vel ); fx->SetAccel( accel ); // RGB---------------- fx->SetRGBStart( rgb1 ); fx->SetRGBEnd( rgb2 ); if (( flags & FX_RGB_PARM_MASK ) == FX_RGB_WAVE ) { fx->SetRGBParm( rgbParm * PI * 0.001f ); } else if ( flags & FX_RGB_PARM_MASK ) { // rgbParm should be a value from 0-100.. fx->SetRGBParm( rgbParm * 0.01f * killTime + theFxHelper.mTime ); } // Alpha---------------- fx->SetAlphaStart( alpha1 ); fx->SetAlphaEnd( alpha2 ); if (( flags & FX_ALPHA_PARM_MASK ) == FX_ALPHA_WAVE ) { fx->SetAlphaParm( alphaParm * PI * 0.001f ); } else if ( flags & FX_ALPHA_PARM_MASK ) { fx->SetAlphaParm( alphaParm * 0.01f * killTime + theFxHelper.mTime ); } fx->SetFlags( flags ); fx->SetShader( shader ); fx->SetRot( rotationDelta ); fx->SetElasticity( bounce ); fx->SetMotionTimeStamp( motionDelay ); fx->SetNumVerts( numVerts ); // Now that we've set our data up, let's process it into a useful format fx->PolyInit(); FX_AddPrimitive( (CEffect**)&fx, killTime ); } return fx; }
/* ============= RB_SurfaceGrid Just copy the grid of points and triangulate ============= */ static void RB_SurfaceGrid( srfBspSurface_t *srf ) { int i, j; float *xyz; float *texCoords, *lightCoords; int16_t *normal; int16_t *tangent; uint16_t *color; int16_t *lightdir; srfVert_t *dv; int rows, irows, vrows; int used; int widthTable[MAX_GRID_SIZE]; int heightTable[MAX_GRID_SIZE]; float lodError; int lodWidth, lodHeight; int numVertexes; int dlightBits; int pshadowBits; //int *vDlightBits; if (RB_SurfaceVaoCached(srf->numVerts, srf->verts, srf->numIndexes, srf->indexes, srf->dlightBits, srf->pshadowBits)) { return; } RB_CheckVao(tess.vao); dlightBits = srf->dlightBits; tess.dlightBits |= dlightBits; pshadowBits = srf->pshadowBits; tess.pshadowBits |= pshadowBits; // determine the allowable discrepance lodError = LodErrorForVolume( srf->lodOrigin, srf->lodRadius ); // determine which rows and columns of the subdivision // we are actually going to use widthTable[0] = 0; lodWidth = 1; for ( i = 1 ; i < srf->width-1 ; i++ ) { if ( srf->widthLodError[i] <= lodError ) { widthTable[lodWidth] = i; lodWidth++; } } widthTable[lodWidth] = srf->width-1; lodWidth++; heightTable[0] = 0; lodHeight = 1; for ( i = 1 ; i < srf->height-1 ; i++ ) { if ( srf->heightLodError[i] <= lodError ) { heightTable[lodHeight] = i; lodHeight++; } } heightTable[lodHeight] = srf->height-1; lodHeight++; // very large grids may have more points or indexes than can be fit // in the tess structure, so we may have to issue it in multiple passes used = 0; while ( used < lodHeight - 1 ) { // see how many rows of both verts and indexes we can add without overflowing do { vrows = ( SHADER_MAX_VERTEXES - tess.numVertexes ) / lodWidth; irows = ( SHADER_MAX_INDEXES - tess.numIndexes ) / ( lodWidth * 6 ); // if we don't have enough space for at least one strip, flush the buffer if ( vrows < 2 || irows < 1 ) { RB_EndSurface(); RB_BeginSurface(tess.shader, tess.fogNum, tess.cubemapIndex ); } else { break; } } while ( 1 ); rows = irows; if ( vrows < irows + 1 ) { rows = vrows - 1; } if ( used + rows > lodHeight ) { rows = lodHeight - used; } numVertexes = tess.numVertexes; xyz = tess.xyz[numVertexes]; normal = tess.normal[numVertexes]; tangent = tess.tangent[numVertexes]; texCoords = tess.texCoords[numVertexes]; lightCoords = tess.lightCoords[numVertexes]; color = tess.color[numVertexes]; lightdir = tess.lightdir[numVertexes]; //vDlightBits = &tess.vertexDlightBits[numVertexes]; for ( i = 0 ; i < rows ; i++ ) { for ( j = 0 ; j < lodWidth ; j++ ) { dv = srf->verts + heightTable[ used + i ] * srf->width + widthTable[ j ]; if ( tess.shader->vertexAttribs & ATTR_POSITION ) { VectorCopy(dv->xyz, xyz); xyz += 4; } if ( tess.shader->vertexAttribs & ATTR_NORMAL ) { VectorCopy4(dv->normal, normal); normal += 4; } if ( tess.shader->vertexAttribs & ATTR_TANGENT ) { VectorCopy4(dv->tangent, tangent); tangent += 4; } if ( tess.shader->vertexAttribs & ATTR_TEXCOORD ) { VectorCopy2(dv->st, texCoords); texCoords += 2; } if ( tess.shader->vertexAttribs & ATTR_LIGHTCOORD ) { VectorCopy2(dv->lightmap, lightCoords); lightCoords += 2; } if ( tess.shader->vertexAttribs & ATTR_COLOR ) { VectorCopy4(dv->color, color); color += 4; } if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION ) { VectorCopy4(dv->lightdir, lightdir); lightdir += 4; } //*vDlightBits++ = dlightBits; } } // add the indexes { int numIndexes; int w, h; h = rows - 1; w = lodWidth - 1; numIndexes = tess.numIndexes; for (i = 0 ; i < h ; i++) { for (j = 0 ; j < w ; j++) { int v1, v2, v3, v4; // vertex order to be reckognized as tristrips v1 = numVertexes + i*lodWidth + j + 1; v2 = v1 - 1; v3 = v2 + lodWidth; v4 = v3 + 1; tess.indexes[numIndexes] = v2; tess.indexes[numIndexes+1] = v3; tess.indexes[numIndexes+2] = v1; tess.indexes[numIndexes+3] = v1; tess.indexes[numIndexes+4] = v3; tess.indexes[numIndexes+5] = v4; numIndexes += 6; } } tess.numIndexes = numIndexes; } tess.numVertexes += rows * lodWidth; used += rows - 1; } }
static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIndexes, glIndex_t *indexes, int dlightBits, int pshadowBits) { int i; glIndex_t *inIndex; srfVert_t *dv; float *xyz, *texCoords, *lightCoords; int16_t *lightdir; int16_t *normal; int16_t *tangent; glIndex_t *outIndex; uint16_t *color; RB_CheckVao(tess.vao); RB_CHECKOVERFLOW( numVerts, numIndexes ); inIndex = indexes; outIndex = &tess.indexes[ tess.numIndexes ]; for ( i = 0 ; i < numIndexes ; i++ ) { *outIndex++ = tess.numVertexes + *inIndex++; } tess.numIndexes += numIndexes; if ( tess.shader->vertexAttribs & ATTR_POSITION ) { dv = verts; xyz = tess.xyz[ tess.numVertexes ]; for ( i = 0 ; i < numVerts ; i++, dv++, xyz+=4 ) VectorCopy(dv->xyz, xyz); } if ( tess.shader->vertexAttribs & ATTR_NORMAL ) { dv = verts; normal = tess.normal[ tess.numVertexes ]; for ( i = 0 ; i < numVerts ; i++, dv++, normal+=4 ) VectorCopy4(dv->normal, normal); } if ( tess.shader->vertexAttribs & ATTR_TANGENT ) { dv = verts; tangent = tess.tangent[ tess.numVertexes ]; for ( i = 0 ; i < numVerts ; i++, dv++, tangent+=4 ) VectorCopy4(dv->tangent, tangent); } if ( tess.shader->vertexAttribs & ATTR_TEXCOORD ) { dv = verts; texCoords = tess.texCoords[tess.numVertexes]; for ( i = 0 ; i < numVerts ; i++, dv++, texCoords+=2 ) VectorCopy2(dv->st, texCoords); } if ( tess.shader->vertexAttribs & ATTR_LIGHTCOORD ) { dv = verts; lightCoords = tess.lightCoords[ tess.numVertexes ]; for ( i = 0 ; i < numVerts ; i++, dv++, lightCoords+=2 ) VectorCopy2(dv->lightmap, lightCoords); } if ( tess.shader->vertexAttribs & ATTR_COLOR ) { dv = verts; color = tess.color[ tess.numVertexes ]; for ( i = 0 ; i < numVerts ; i++, dv++, color+=4 ) VectorCopy4(dv->color, color); } if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION ) { dv = verts; lightdir = tess.lightdir[ tess.numVertexes ]; for ( i = 0 ; i < numVerts ; i++, dv++, lightdir+=4 ) VectorCopy4(dv->lightdir, lightdir); } #if 0 // nothing even uses vertex dlightbits for ( i = 0 ; i < numVerts ; i++ ) { tess.vertexDlightBits[ tess.numVertexes + i ] = dlightBits; } #endif tess.dlightBits |= dlightBits; tess.pshadowBits |= pshadowBits; tess.numVertexes += numVerts; }