mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-12 08:11:10 +02:00
239 lines
5.0 KiB
C++
239 lines
5.0 KiB
C++
#include "precompiled.h"
|
|
#pragma hdrstop
|
|
|
|
#include "tr_local.h"
|
|
|
|
static srfTriangles_t* g_skyDomeTri = NULL;
|
|
static const idMaterial* g_skyDomeMat = NULL;
|
|
|
|
static idCVar r_skyDome("r_skyDome", "1", CVAR_RENDERER | CVAR_BOOL, "render procedural skydome");
|
|
static idCVar r_skyDomeRadius("r_skyDomeRadius", "8192", CVAR_RENDERER | CVAR_FLOAT, "skydome radius (world units)");
|
|
static idCVar r_skyDomeRings("r_skyDomeRings", "24", CVAR_RENDERER | CVAR_INTEGER, "skydome vertical subdivisions");
|
|
static idCVar r_skyDomeSegments("r_skyDomeSegments", "48", CVAR_RENDERER | CVAR_INTEGER, "skydome horizontal subdivisions");
|
|
|
|
static void R_UploadSkyDomeMeshToVertexCache(srfTriangles_t* tri) {
|
|
if (!tri) {
|
|
return;
|
|
}
|
|
|
|
if (tri->ambientCache) {
|
|
vertexCache.Free(tri->ambientCache);
|
|
tri->ambientCache = 0;
|
|
}
|
|
|
|
if (tri->indexCache) {
|
|
vertexCache.Free(tri->indexCache);
|
|
tri->indexCache = 0;
|
|
}
|
|
|
|
vertexCache.Alloc(
|
|
tri->verts,
|
|
tri->numVerts * sizeof(tri->verts[0]),
|
|
&tri->ambientCache
|
|
);
|
|
|
|
vertexCache.Alloc(
|
|
tri->indexes,
|
|
tri->numIndexes * sizeof(tri->indexes[0]),
|
|
&tri->indexCache
|
|
);
|
|
}
|
|
|
|
// Build a hemisphere, top half. Inside-facing draw.
|
|
static srfTriangles_t* R_BuildSkyDomeMesh(int rings, int segs, float radius) {
|
|
rings = Max(rings, 4);
|
|
segs = Max(segs, 8);
|
|
|
|
const int vertsPerRing = segs + 1;
|
|
const int numVerts = (rings + 1) * vertsPerRing;
|
|
|
|
const int numQuads = rings * segs;
|
|
const int numTris = numQuads * 2;
|
|
const int numIndexes = numTris * 3;
|
|
|
|
srfTriangles_t* tri = R_AllocStaticTriSurf();
|
|
R_AllocStaticTriSurfVerts(tri, numVerts);
|
|
R_AllocStaticTriSurfIndexes(tri, numIndexes);
|
|
|
|
idDrawVert* v = tri->verts;
|
|
glIndex_t* idx = tri->indexes;
|
|
|
|
int vi = 0;
|
|
|
|
for (int r = 0; r <= rings; r++) {
|
|
const float t = (float)r / (float)rings;
|
|
const float phi = t * idMath::HALF_PI;
|
|
|
|
const float sinPhi = idMath::Sin(phi);
|
|
const float cosPhi = idMath::Cos(phi);
|
|
|
|
for (int s = 0; s <= segs; s++) {
|
|
const float u = (float)s / (float)segs;
|
|
const float theta = u * idMath::TWO_PI;
|
|
|
|
const float sinTheta = idMath::Sin(theta);
|
|
const float cosTheta = idMath::Cos(theta);
|
|
|
|
idVec3 dir;
|
|
dir.x = cosTheta * cosPhi;
|
|
dir.y = sinTheta * cosPhi;
|
|
dir.z = sinPhi;
|
|
|
|
v[vi].xyz = dir * radius;
|
|
|
|
float uu = idMath::ATan(dir.y, dir.x) / idMath::TWO_PI + 0.5f;
|
|
float vv = idMath::ASin(idMath::ClampFloat(-1.0f, 1.0f, dir.z)) / idMath::PI + 0.5f;
|
|
|
|
vv = 1.0f - vv;
|
|
|
|
v[vi].st.x = uu;
|
|
v[vi].st.y = vv;
|
|
|
|
v[vi].normal = dir;
|
|
v[vi].tangents[0].Set(-sinTheta, cosTheta, 0.0f);
|
|
v[vi].tangents[1].Set(0.0f, 0.0f, 1.0f);
|
|
|
|
v[vi].color[0] = 255;
|
|
v[vi].color[1] = 255;
|
|
v[vi].color[2] = 255;
|
|
v[vi].color[3] = 255;
|
|
|
|
vi++;
|
|
}
|
|
}
|
|
|
|
int ii = 0;
|
|
|
|
for (int r = 0; r < rings; r++) {
|
|
for (int s = 0; s < segs; s++) {
|
|
const int i0 = r * vertsPerRing + s;
|
|
const int i1 = i0 + 1;
|
|
const int i2 = (r + 1) * vertsPerRing + s;
|
|
const int i3 = i2 + 1;
|
|
|
|
idx[ii++] = i0;
|
|
idx[ii++] = i2;
|
|
idx[ii++] = i1;
|
|
|
|
idx[ii++] = i1;
|
|
idx[ii++] = i2;
|
|
idx[ii++] = i3;
|
|
}
|
|
}
|
|
|
|
tri->numVerts = numVerts;
|
|
tri->numIndexes = numIndexes;
|
|
|
|
R_BoundTriSurf(tri);
|
|
|
|
R_UploadSkyDomeMeshToVertexCache(tri);
|
|
|
|
return tri;
|
|
}
|
|
|
|
void R_InitSkyDome() {
|
|
if (g_skyDomeTri) {
|
|
return;
|
|
}
|
|
|
|
g_skyDomeTri = R_BuildSkyDomeMesh(
|
|
r_skyDomeRings.GetInteger(),
|
|
r_skyDomeSegments.GetInteger(),
|
|
r_skyDomeRadius.GetFloat()
|
|
);
|
|
}
|
|
|
|
void R_ShutdownSkyDome() {
|
|
if (g_skyDomeTri) {
|
|
if (g_skyDomeTri->ambientCache) {
|
|
vertexCache.Free(g_skyDomeTri->ambientCache);
|
|
g_skyDomeTri->ambientCache = 0;
|
|
}
|
|
|
|
if (g_skyDomeTri->indexCache) {
|
|
vertexCache.Free(g_skyDomeTri->indexCache);
|
|
g_skyDomeTri->indexCache = 0;
|
|
}
|
|
|
|
R_FreeStaticTriSurf(g_skyDomeTri);
|
|
g_skyDomeTri = NULL;
|
|
}
|
|
|
|
g_skyDomeMat = NULL;
|
|
}
|
|
|
|
static const idMaterial* R_GetSkyDomeMaterial() {
|
|
return backEnd.viewDef->renderView.skyDomeMaterial;
|
|
}
|
|
|
|
void RB_DrawSkyDome(const viewDef_t* viewDef) {
|
|
if (!r_skyDome.GetBool()) {
|
|
return;
|
|
}
|
|
|
|
if (!g_skyDomeTri || !g_skyDomeTri->ambientCache || !g_skyDomeTri->indexCache) {
|
|
return;
|
|
}
|
|
|
|
g_skyDomeMat = R_GetSkyDomeMaterial();
|
|
|
|
if (!g_skyDomeMat) {
|
|
return;
|
|
}
|
|
|
|
glDepthMask(GL_FALSE);
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
|
|
float mv[16];
|
|
memcpy(mv, backEnd.viewDef->worldSpace.modelViewMatrix, sizeof(mv));
|
|
|
|
mv[12] = 0.0f;
|
|
mv[13] = 0.0f;
|
|
mv[14] = 0.0f;
|
|
|
|
glLoadMatrixf(mv);
|
|
|
|
GL_SelectTexture(0);
|
|
|
|
const shaderStage_t* stage = g_skyDomeMat->GetStage(0);
|
|
|
|
if (stage && stage->texture.image) {
|
|
stage->texture.image->Bind();
|
|
}
|
|
else {
|
|
globalImages->whiteImage->Bind();
|
|
}
|
|
|
|
idDrawVert* verts = (idDrawVert*)vertexCache.Position(g_skyDomeTri->ambientCache);
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glVertexPointer(
|
|
3,
|
|
GL_FLOAT,
|
|
sizeof(idDrawVert),
|
|
verts->xyz.ToFloatPtr()
|
|
);
|
|
|
|
glTexCoordPointer(
|
|
2,
|
|
GL_FLOAT,
|
|
sizeof(idDrawVert),
|
|
verts->st.ToFloatPtr()
|
|
);
|
|
|
|
glGeometryFlagf(GEOMETRY_FLAG_UNLIT);
|
|
RB_DrawElementsWithCounters(g_skyDomeTri);
|
|
glGeometryFlagf(GEOMETRY_FLAG_NONE);
|
|
|
|
glPopMatrix();
|
|
|
|
glDepthMask(GL_TRUE);
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
} |