Skip to content

Commit

Permalink
Refactor: Store the variant material for a masked wall in vissprite
Browse files Browse the repository at this point in the history
  • Loading branch information
danij-deng committed Jan 25, 2012
1 parent d7ebc28 commit 51df6f5
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 64 deletions.
6 changes: 5 additions & 1 deletion doomsday/engine/portable/include/materialvariant.h
Expand Up @@ -28,6 +28,7 @@

struct texturevariant_s;
struct texturevariantspecification_s;
struct materialvariant_s;

typedef struct materialvariantspecification_s {
materialcontext_t context;
Expand All @@ -46,6 +47,9 @@ enum {
};

typedef struct materialsnapshot_s {
/// Variant Material used to derive this snapshot.
struct materialvariant_s* material;

/// @c true= this material is entirely opaque.
boolean isOpaque;

Expand Down Expand Up @@ -141,7 +145,7 @@ materialvariant_t* MaterialVariant_TranslationNext(materialvariant_t* mat);
/// @return Translated 'current' MaterialVariant if set, else this.
materialvariant_t* MaterialVariant_TranslationCurrent(materialvariant_t* mat);

/// @return Translation position [0...1]
/// @return Translation position [0..1]
float MaterialVariant_TranslationPoint(materialvariant_t* mat);

/**
Expand Down
9 changes: 5 additions & 4 deletions doomsday/engine/portable/include/r_things.h
Expand Up @@ -34,6 +34,8 @@
#include "materials.h"
#include "rend_model.h"

struct materialvariant_s;

// Sprites are patches with a special naming convention so they can be
// recognized by R_InitSprites. The sprite and frame specified by a
// mobj is range checked at run time.
Expand Down Expand Up @@ -66,16 +68,15 @@ typedef enum {
} visspritetype_t;

typedef struct rendmaskedwallparams_s {
DGLuint tex;
int magMode;
boolean masked;
struct materialvariant_s* material;
blendmode_t blendMode; // Blendmode to be used when drawing
// (two sided mid textures only)
struct wall_vertex_s {
float pos[3]; // x y and z coordinates.
float color[4];
} vertices[4];
float texCoord[2][2]; // u and v coordinates.
float texOffset[2];
float length; // Precalculated 2D distance from v1 > v2

DGLuint modTex; // Texture to modulate with.
float modTexCoord[2][2]; // u and v coordinates.
Expand Down
3 changes: 3 additions & 0 deletions doomsday/engine/portable/src/materials.c
Expand Up @@ -1161,6 +1161,7 @@ void Materials_InitSnapshot(materialsnapshot_t* ms)
ms->textures[i] = NULL;
}

ms->material = NULL;
ms->size.width = ms->size.height = 0;
ms->glowing = 0;
ms->isOpaque = true;
Expand Down Expand Up @@ -1248,6 +1249,7 @@ const materialsnapshot_t* updateMaterialSnapshot(materialvariant_t* variant,
MaterialVariant_SetSnapshotPrepareFrame(variant, frameCount);

Materials_InitSnapshot(snapshot);
snapshot->material = variant;
memcpy(&snapshot->size, Material_Size(mat), sizeof snapshot->size);

if(0 == snapshot->size.width && 0 == snapshot->size.height) return snapshot;
Expand Down Expand Up @@ -1341,6 +1343,7 @@ const materialsnapshot_t* Materials_PrepareVariant2(materialvariant_t* variant,
Con_Error("Materials::Prepare: Failed on allocation of %lu bytes for new MaterialSnapshot.", (unsigned long) sizeof *snapshot);
snapshot = MaterialVariant_AttachSnapshot(variant, snapshot);
Materials_InitSnapshot(snapshot);
snapshot->material = variant;

// Update the snapshot right away.
updateSnapshot = true;
Expand Down
47 changes: 17 additions & 30 deletions doomsday/engine/portable/src/rend_main.c
Expand Up @@ -672,11 +672,9 @@ int RIT_FirstDynlightIterator(const dynlight_t* dyn, void* paramaters)
* of sprites. This is necessary because all masked polygons must be
* rendered back-to-front, or there will be alpha artifacts along edges.
*/
void Rend_AddMaskedPoly(const rvertex_t* rvertices,
const ColorRawf* rcolors, float wallLength,
DGLuint tex, int magMode, float texWidth, float texHeight,
const float texOffset[2], blendmode_t blendMode,
uint lightListIdx, float glow, boolean masked)
void Rend_AddMaskedPoly(const rvertex_t* rvertices, const ColorRawf* rcolors,
float wallLength, materialvariant_t* material, const float texOffset[2],
blendmode_t blendMode, uint lightListIdx, float glow)
{
vissprite_t* vis = R_NewVisSprite();
float midpoint[3];
Expand All @@ -691,9 +689,12 @@ void Rend_AddMaskedPoly(const rvertex_t* rvertices,
vis->center[VY] = midpoint[VY];
vis->center[VZ] = midpoint[VZ];
vis->distance = Rend_PointDist2D(midpoint);
vis->data.wall.tex = tex;
vis->data.wall.magMode = magMode;
vis->data.wall.masked = masked;
vis->data.wall.material = material;
vis->data.wall.texOffset[VX] = texOffset? texOffset[VX] : 0;
vis->data.wall.texOffset[VY] = texOffset? texOffset[VY] : 0;
vis->data.wall.length = wallLength;
vis->data.wall.blendMode = blendMode;

for(i = 0; i < 4; ++i)
{
vis->data.wall.vertices[i].pos[VX] = rvertices[i].pos[VX];
Expand All @@ -707,15 +708,6 @@ void Rend_AddMaskedPoly(const rvertex_t* rvertices,
}
}

vis->data.wall.texCoord[0][VX] = (texOffset? texOffset[VX] / texWidth : 0);
vis->data.wall.texCoord[1][VX] =
vis->data.wall.texCoord[0][VX] + wallLength / texWidth;
vis->data.wall.texCoord[0][VY] = (texOffset? texOffset[VY] / texHeight : 0);
vis->data.wall.texCoord[1][VY] =
vis->data.wall.texCoord[0][VY] +
(rvertices[3].pos[VZ] - rvertices[0].pos[VZ]) / texHeight;
vis->data.wall.blendMode = blendMode;

//// \fixme Semitransparent masked polys arn't lit atm
if(glow < 1 && lightListIdx && numTexUnits > 1 && envModAdd &&
!(rcolors[0].rgba[CA] < 1))
Expand Down Expand Up @@ -1201,21 +1193,16 @@ static boolean renderWorldPoly(rvertex_t* rvertices, uint numVertices,
* This is needed because all masked polys must be sorted (sprites
* are masked polys). Otherwise there will be artifacts.
*/
Rend_AddMaskedPoly(rvertices, rcolors, *p->segLength,
primaryRTU->tex, primaryRTU->magMode, msA->size.width, msA->size.height,
p->texOffset,
p->blendMode, p->lightListIdx, glowing,
!msA->isOpaque);
Rend_AddMaskedPoly(rvertices, rcolors, *p->segLength, msA->material,
p->texOffset, p->blendMode, p->lightListIdx, glowing);

R_FreeRendTexCoords(primaryCoords);
if(interCoords)
R_FreeRendTexCoords(interCoords);
if(modCoords)
R_FreeRendTexCoords(modCoords);
if(shinyTexCoords)
R_FreeRendTexCoords(shinyTexCoords);
R_FreeRendColors(rcolors);
if(shinyColors)
R_FreeRendColors(shinyColors);

if(interCoords) R_FreeRendTexCoords(interCoords);
if(modCoords) R_FreeRendTexCoords(modCoords);
if(shinyTexCoords) R_FreeRendTexCoords(shinyTexCoords);
if(shinyColors) R_FreeRendColors(shinyColors);

return false; // We HAD to use a vissprite, so it MUST not be opaque.
}
Expand Down
66 changes: 37 additions & 29 deletions doomsday/engine/portable/src/rend_sprite.c
Expand Up @@ -581,9 +581,21 @@ static void selectTexUnits(int count)
*/
void Rend_RenderMaskedWall(rendmaskedwallparams_t* params)
{
const materialsnapshot_t* ms = NULL;
GLenum normalTarget, dynTarget;
boolean withDyn = false;
int normal = 0, dyn = 1;
float texCoord[2][2]; // u and v coordinates.

if(renderTextures)
{
ms = Materials_PrepareVariant(params->material);
texCoord[0][VX] = params->texOffset[VX] / ms->size.width;
texCoord[1][VX] = texCoord[0][VX] + params->length / ms->size.width;
texCoord[0][VY] = params->texOffset[VY] / ms->size.height;
texCoord[1][VY] = texCoord[0][VY] +
(params->vertices[3].pos[VZ] - params->vertices[0].pos[VZ]) / ms->size.height;
}

// Do we have a dynamic light to blend with?
// This only happens when multitexturing is enabled.
Expand Down Expand Up @@ -614,21 +626,15 @@ void Rend_RenderMaskedWall(rendmaskedwallparams_t* params)

// The actual texture.
glActiveTexture(IS_MUL ? GL_TEXTURE1 : GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, renderTextures ? params->tex : 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, params->magMode);
if(GL_state.features.texFilterAniso)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_GetTexAnisoMul(texAniso));
glBindTexture(GL_TEXTURE_2D, ms? MSU_gltexture(ms, MTU_PRIMARY) : 0);

withDyn = true;
}
else
{
GL_ModulateTexture(1);

glBindTexture(GL_TEXTURE_2D, renderTextures? params->tex : 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, params->magMode);
if(GL_state.features.texFilterAniso)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_GetTexAnisoMul(texAniso));
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, ms? MSU_gltexture(ms, MTU_PRIMARY) : 0);
normal = 0;
}

Expand All @@ -638,28 +644,30 @@ void Rend_RenderMaskedWall(rendmaskedwallparams_t* params)
// Most masked walls need wrapping, though. What we need to do is
// look at the texture coordinates and see if they require texture
// wrapping.
if(params->masked)
/// @fixme The texture state should NOT be modified here. Handle
/// by selecting another variant at vissprite creation time.
if(ms && !ms->isOpaque)
{
if(withDyn)
{
glActiveTexture(IS_MUL ? GL_TEXTURE1 : GL_TEXTURE0);
}

if(params->texCoord[0][VX] < 0 || params->texCoord[0][VX] > 1 ||
params->texCoord[1][VX] < 0 || params->texCoord[1][VX] > 1)
if(texCoord[0][VX] < 0 || texCoord[0][VX] > 1 ||
texCoord[1][VX] < 0 || texCoord[1][VX] > 1)
{
// The texcoords are out of the normal [0,1] range.
// The texcoords are out of the normal [0..1] range.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
}
else
{
// Visible portion is within the actual [0,1] range.
// Visible portion is within the actual [0..1] range.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
}

// Clamp on the vertical axis if the coords are in the normal [0, 1] range.
if(!(params->texCoord[0][VY] < 0 || params->texCoord[0][VY] > 1 ||
params->texCoord[1][VY] < 0 || params->texCoord[1][VY] > 1))
// Clamp on the vertical axis if the coords are in the normal [0..1] range.
if(!(texCoord[0][VY] < 0 || texCoord[0][VY] > 1 ||
texCoord[1][VY] < 0 || texCoord[1][VY] > 1))
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
GL_BlendMode(params->blendMode);
Expand All @@ -675,7 +683,7 @@ void Rend_RenderMaskedWall(rendmaskedwallparams_t* params)
{
glBegin(GL_QUADS);
glColor4fv(params->vertices[0].color);
glMultiTexCoord2f(normalTarget, params->texCoord[0][0], params->texCoord[1][1]);
glMultiTexCoord2f(normalTarget, texCoord[0][0], texCoord[1][1]);

glMultiTexCoord2f(dynTarget, params->modTexCoord[0][0], params->modTexCoord[1][1]);

Expand All @@ -684,7 +692,7 @@ void Rend_RenderMaskedWall(rendmaskedwallparams_t* params)
params->vertices[0].pos[VY]);

glColor4fv(params->vertices[1].color);
glMultiTexCoord2f(normalTarget, params->texCoord[0][0], params->texCoord[0][1]);
glMultiTexCoord2f(normalTarget, texCoord[0][0], texCoord[0][1]);

glMultiTexCoord2f(dynTarget, params->modTexCoord[0][0], params->modTexCoord[1][0]);

Expand All @@ -693,7 +701,7 @@ void Rend_RenderMaskedWall(rendmaskedwallparams_t* params)
params->vertices[1].pos[VY]);

glColor4fv(params->vertices[3].color);
glMultiTexCoord2f(normalTarget, params->texCoord[1][0], params->texCoord[0][1]);
glMultiTexCoord2f(normalTarget, texCoord[1][0], texCoord[0][1]);

glMultiTexCoord2f(dynTarget, params->modTexCoord[0][1], params->modTexCoord[1][0]);

Expand All @@ -702,7 +710,7 @@ void Rend_RenderMaskedWall(rendmaskedwallparams_t* params)
params->vertices[3].pos[VY]);

glColor4fv(params->vertices[2].color);
glMultiTexCoord2f(normalTarget, params->texCoord[1][0], params->texCoord[1][1]);
glMultiTexCoord2f(normalTarget, texCoord[1][0], texCoord[1][1]);

glMultiTexCoord2f(dynTarget, params->modTexCoord[0][1], params->modTexCoord[1][1]);

Expand All @@ -719,39 +727,39 @@ void Rend_RenderMaskedWall(rendmaskedwallparams_t* params)
{
glBegin(GL_QUADS);
glColor4fv(params->vertices[0].color);
glTexCoord2f(params->texCoord[0][0], params->texCoord[1][1]);
glTexCoord2f(texCoord[0][0], texCoord[1][1]);

glVertex3f(params->vertices[0].pos[VX],
params->vertices[0].pos[VZ],
params->vertices[0].pos[VY]);

glColor4fv(params->vertices[1].color);
glTexCoord2f(params->texCoord[0][0], params->texCoord[0][1]);
glTexCoord2f(texCoord[0][0], texCoord[0][1]);

glVertex3f(params->vertices[1].pos[VX],
params->vertices[1].pos[VZ],
params->vertices[1].pos[VY]);

glColor4fv(params->vertices[3].color);
glTexCoord2f(params->texCoord[1][0], params->texCoord[0][1]);
glTexCoord2f(texCoord[1][0], texCoord[0][1]);

glVertex3f(params->vertices[3].pos[VX],
params->vertices[3].pos[VZ],
params->vertices[3].pos[VY]);

glColor4fv(params->vertices[2].color);
glTexCoord2f(params->texCoord[1][0], params->texCoord[1][1]);
glTexCoord2f(texCoord[1][0], texCoord[1][1]);

glVertex3f(params->vertices[2].pos[VX],
params->vertices[2].pos[VZ],
params->vertices[2].pos[VY]);
glEnd();

}

if(params->masked && renderTextures)
{ // Restore the original texture state.
glBindTexture(GL_TEXTURE_2D, params->tex);
if(ms && !ms->isOpaque)
{
// Restore the original texture state.
glBindTexture(GL_TEXTURE_2D, MSU_gltexture(ms, MTU_PRIMARY));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
Expand Down

0 comments on commit 51df6f5

Please sign in to comment.