forked from Mirrors/openclonk
Normal map support for lights
- The light direction change isn't really consistent, as I can only give GL the vectors at the triangle edges. So for deep rays, the light distribution often ends up being significantly different than for short rays. - I *am* distorting the normal map vectors, quite badly actually. I'll leave it for the moment, because it definetely looks best for the light vectors, but I will have to correct that a bit once I have the time.issue1247
parent
18c8af73a8
commit
d1c28227f3
|
@ -54,6 +54,13 @@ float queryMatMap(int pix)
|
|||
#endif
|
||||
}
|
||||
|
||||
float dotc(vec2 v1, vec2 v2)
|
||||
{
|
||||
vec3 v1p = normalize(vec3(v1, 0.3));
|
||||
vec3 v2p = normalize(vec3(v2, 0.3));
|
||||
return dot(v1p, v2p);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
|
@ -112,19 +119,21 @@ void main()
|
|||
vec4 lopx = texture2D(landscapeTex[0], otherCoo);
|
||||
|
||||
// Get material pixels
|
||||
|
||||
float mi = queryMatMap(f2i(lpx.r));
|
||||
|
||||
vec4 mpx = texture3D(materialTex, vec3(texCoo * resolution / vec2(512.0, 512.0) * vec2(4.0, 4.0), mi));
|
||||
vec2 tcoo = texCoo * resolution / vec2(512.0, 512.0) * vec2(4.0, 4.0);
|
||||
vec4 mpx = texture3D(materialTex, vec3(tcoo, mi));
|
||||
vec4 npx = texture3D(materialTex, vec3(tcoo, mi+0.5));
|
||||
float omi = queryMatMap(f2i(lopx.r));
|
||||
vec4 ompx = texture3D(materialTex, vec3(texCoo * resolution / vec2(512.0, 512.0) * vec2(4.0, 4.0), omi));
|
||||
vec4 ompx = texture3D(materialTex, vec3(tcoo, omi));
|
||||
|
||||
// Brightness
|
||||
float ambientBright = texture2D(lightTex, gl_TexCoord[1].st).r*2.0, shadeBright = ambientBright;
|
||||
vec2 normal = (2.0 * mix(rlpx.yz, lpx.yz, spx.a) - vec2(1.0, 1.0));
|
||||
vec2 normal2 = (2.0 * lopx.yz - vec2(1.0, 1.0));
|
||||
float bright = ambientBright + shadeBright * dot(normal, vec2(0.0, -1.0));
|
||||
float bright2 = ambientBright + shadeBright * dot(normal2, vec2(0.0, -1.0));
|
||||
// Brightness
|
||||
vec4 lipx = texture2D(lightTex, gl_TexCoord[1].st);
|
||||
float ambientBright = lipx.r, shadeBright = ambientBright;
|
||||
vec2 normal = (mix(rlpx.yz, lpx.yz, spx.a) + npx.xy - vec2(1.0, 1.0));
|
||||
vec2 normal2 = (lopx.yz + npx.xy - vec2(1.0, 1.0));
|
||||
vec2 light_dir = vec2(1.0, 1.0) - lipx.yz * 3;
|
||||
float bright = 2.0 * shadeBright * dotc(normal, light_dir);
|
||||
float bright2 = 2.0 * shadeBright * dotc(normal2, light_dir);
|
||||
|
||||
gl_FragColor = mix(
|
||||
vec4(bright2 * ompx.rgb, ompx.a),
|
||||
|
|
|
@ -230,7 +230,7 @@ void C4Viewport::Draw(C4TargetFacet &cgo0, bool fDrawOverlay)
|
|||
// Update FoW
|
||||
if (pFoW)
|
||||
{
|
||||
pFoW->Set(C4Rect(
|
||||
pFoW->Update(C4Rect(
|
||||
int32_t(cgo.TargetX), int32_t(cgo.TargetY),
|
||||
cgo.Wdt + 1, cgo.Hgt + 1));
|
||||
|
||||
|
@ -264,6 +264,8 @@ void C4Viewport::Draw(C4TargetFacet &cgo0, bool fDrawOverlay)
|
|||
// Draw overlay
|
||||
if (!Game.C4S.Head.Film || !Game.C4S.Head.Replay) Game.DrawCursors(cgo, Player);
|
||||
|
||||
//pFoW->Render(&cgo);
|
||||
|
||||
if (fDrawOverlay)
|
||||
{
|
||||
// Determine zoom of overlay
|
||||
|
@ -626,7 +628,7 @@ bool C4Viewport::Init(int32_t iPlayer, bool fSetTempOnly)
|
|||
}
|
||||
// Initialize FoW
|
||||
if (::Landscape.pFoW)
|
||||
pFoW = new C4FoWRegion(::Landscape.pFoW);
|
||||
pFoW = new C4FoWRegion(::Landscape.pFoW, ::Players.Get(iPlayer));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -617,8 +617,9 @@ void C4FoWRay::Prune(int32_t y)
|
|||
iRightEndY = y;
|
||||
}
|
||||
|
||||
C4FoWRegion::C4FoWRegion(C4FoW *pFoW)
|
||||
C4FoWRegion::C4FoWRegion(C4FoW *pFoW, C4Player *pPlayer)
|
||||
: pFoW(pFoW)
|
||||
, pPlayer(pPlayer)
|
||||
, hFrameBufDraw(0), hFrameBufRead(0)
|
||||
, Region(0,0,0,0), OldRegion(0,0,0,0)
|
||||
, pSurface(NULL), pBackSurface(NULL)
|
||||
|
@ -630,7 +631,7 @@ C4FoWRegion::~C4FoWRegion()
|
|||
Clear();
|
||||
}
|
||||
|
||||
bool C4FoWRegion::Create()
|
||||
bool C4FoWRegion::BindFramebuf()
|
||||
{
|
||||
|
||||
// Flip texture
|
||||
|
@ -691,6 +692,12 @@ void C4FoWRegion::Clear()
|
|||
delete pBackSurface; pBackSurface = NULL;
|
||||
}
|
||||
|
||||
void C4FoWRegion::Update(C4Rect r)
|
||||
{
|
||||
// Set the new region
|
||||
Region = r;
|
||||
}
|
||||
|
||||
void C4FoWRegion::Render(const C4TargetFacet *pOnScreen)
|
||||
{
|
||||
// Update FoW at interesting location
|
||||
|
@ -705,7 +712,7 @@ void C4FoWRegion::Render(const C4TargetFacet *pOnScreen)
|
|||
|
||||
// Create & bind the frame buffer
|
||||
pDraw->StorePrimaryClipper();
|
||||
if(!Create())
|
||||
if(!BindFramebuf())
|
||||
{
|
||||
pDraw->RestorePrimaryClipper();
|
||||
return;
|
||||
|
@ -722,8 +729,8 @@ void C4FoWRegion::Render(const C4TargetFacet *pOnScreen)
|
|||
gluOrtho2D(0, getSurface()->Wdt, getSurface()->Hgt, 0);
|
||||
|
||||
// Clear texture contents
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
//glClear(GL_COLOR_BUFFER_BIT);
|
||||
glClearColor(0.0f, 0.5f/1.5f, 0.5f/1.5f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Copy over the old state
|
||||
if (OldRegion.Wdt > 0) {
|
||||
|
@ -734,29 +741,33 @@ void C4FoWRegion::Render(const C4TargetFacet *pOnScreen)
|
|||
dy1 = Region.y + Region.Hgt - OldRegion.y - OldRegion.Hgt;
|
||||
|
||||
glBlitFramebufferEXT(
|
||||
Max(0, -dx0), Max(0, -dy0),
|
||||
OldRegion.Wdt - Max(0, -dx1), OldRegion.Hgt - Max(0, -dy1),
|
||||
Max(0, dx0), Max(0, dy0),
|
||||
Region.Wdt - Max(0, dx1), Region.Hgt - Max(0, dy1),
|
||||
Max(0, dx0), Max(0, -dy1),
|
||||
OldRegion.Wdt - Max(0, -dx1), OldRegion.Hgt - Max(0, dy0),
|
||||
Max(0, -dx0), Max(0, dy1),
|
||||
Region.Wdt - Max(0, dx1), Region.Hgt - Max(0, -dy0),
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
|
||||
glCheck();
|
||||
|
||||
// Fade out
|
||||
glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
|
||||
glColor4f(0.0f, 0.0f, 0.0f, 0.8f);
|
||||
// Fade out. Note we constantly vary the alpha factor all the time -
|
||||
// this is barely visible but makes it a lot less likely that we
|
||||
// hit cases where we add the same thing every time, but still don't
|
||||
// converge to the same color due to rounding.
|
||||
int iAdd = (Game.FrameCounter/3) % 2;
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glColor4f(0.0f, 0.5f/1.5f, 0.5f/1.5f, 1.0f/16.0f+iAdd*1.0f/256.0f);
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2i(0, 0);
|
||||
glVertex2i(getSurface()->Wdt, 0);
|
||||
glVertex2i(getSurface()->Wdt, getSurface()->Hgt);
|
||||
glVertex2i(0, getSurface()->Hgt);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
// Render FoW to frame buffer object
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
pFoW->Render(this);
|
||||
|
||||
|
||||
// Done!
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
|
@ -1265,112 +1276,168 @@ void C4FoWLightSection::Render(C4FoWRegion *pRegion, const C4TargetFacet *pOnScr
|
|||
}
|
||||
}
|
||||
|
||||
// Draw the fan
|
||||
#define LIGHT if(pOnScreen) glColor3f(1.0f, 0.0f, 0.0f); else glColor3f(0.1f, 0.1f, 0.1f)
|
||||
#define DARK if(pOnScreen) glColor3f(0.5f, 0.5f, 0.0f); else glColor3f(0.0f, 0.0f, 0.0f)
|
||||
#define BEGIN_TRIANGLE if(pOnScreen) glBegin(GL_LINE_LOOP)
|
||||
#define END_TRIANGLE if(pOnScreen) glEnd()
|
||||
LIGHT;
|
||||
glShadeModel(GL_FLAT);
|
||||
glBegin(pOnScreen ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
|
||||
if (!pOnScreen)
|
||||
glVertex2f(float(pLight->getX() - pRegion->getRegion().x),
|
||||
float(pLight->getY() - pRegion->getRegion().y));
|
||||
for (i = 0; i < iRayCnt; i++) {
|
||||
if (i == 0 || gFanRX[i-1] != gFanLX[i] || gFanRY[i-1] != gFanLY[i])
|
||||
glVertex2f(gFanLX[i], gFanLY[i]);
|
||||
if (gFanLX[i] != gFanRX[i] || gFanLY[i] != gFanRY[i])
|
||||
glVertex2f(gFanRX[i], gFanRY[i]);
|
||||
}
|
||||
glEnd();
|
||||
// Calculate position of the light in the buffer
|
||||
float gLightX = transX(0,0) - pRegion->getRegion().x,
|
||||
gLightY = transY(0,0) - pRegion->getRegion().y;
|
||||
|
||||
// Draw the fade
|
||||
glShadeModel(GL_SMOOTH);
|
||||
if(!pOnScreen) glBegin(GL_TRIANGLES);
|
||||
// Here's the master plan for updating the lights texture. We
|
||||
// want to add intensity (R channel) as well as the normal (GB channels).
|
||||
// Normals are obviously meant to be though of as signed, though,
|
||||
// so the equation we want would be something like
|
||||
//
|
||||
// R_new = BoundBy(R_old + R, 0.0, 1.0)
|
||||
// G_new = BoundBy(G_old + G - 0.5, 0.0, 1.0)
|
||||
// B_new = BoundBy(B_old + B - 0.5, 0.0, 1.0)
|
||||
//
|
||||
// It seems we can't get that directly though - glBlendFunc only talks
|
||||
// about two operands. Even if we make two passes, we have to take
|
||||
// care that that we don't over- or underflow in the intermediate pass.
|
||||
//
|
||||
// Therefore, we store G/1.5 instead of G, losing a bit of accuracy,
|
||||
// but allowing us to formulate the following approximation without
|
||||
// overflows:
|
||||
//
|
||||
// G_new = BoundBy(BoundBy(G_old + G / 1.5), 0.0, 1.0) - 0.5 / 1.5, 0.0, 1.0)
|
||||
// B_new = BoundBy(BoundBy(B_old + B / 1.5), 0.0, 1.0) - 0.5 / 1.5, 0.0, 1.0)
|
||||
|
||||
for (i = 0; i < iRayCnt; i++) {
|
||||
// Two passes
|
||||
for(int iPass = 0; iPass < (pOnScreen ? 1 : 2); iPass++) {
|
||||
|
||||
// The quad. Will be empty if fan points match
|
||||
if (gFanLX[i] != gFanRX[i] || gFanLY[i] != gFanRY[i]) {
|
||||
|
||||
// upper triangle
|
||||
BEGIN_TRIANGLE;
|
||||
LIGHT; glVertex2f(gFanLX[i], gFanLY[i]);
|
||||
LIGHT; glVertex2f(gFanRX[i], gFanRY[i]);
|
||||
DARK; glVertex2f(gFadeLX[i], gFadeLY[i]);
|
||||
END_TRIANGLE;
|
||||
|
||||
// lower triangle, if necessary
|
||||
if (gFadeLX[i] != gFadeRX[i] || gFadeLY[i] != gFadeRY[i]) {
|
||||
BEGIN_TRIANGLE;
|
||||
LIGHT; glVertex2f(gFanRX[i], gFanRY[i]);
|
||||
DARK; glVertex2f(gFadeRX[i], gFadeRY[i]);
|
||||
DARK; glVertex2f(gFadeLX[i], gFadeLY[i]);
|
||||
END_TRIANGLE;
|
||||
}
|
||||
// Pass 2: Subtract
|
||||
if (!pOnScreen && iPass == 1) {
|
||||
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
}
|
||||
|
||||
// No intermediate fade for last point
|
||||
if (i+1 >= iRayCnt) continue;
|
||||
|
||||
// Ascending?
|
||||
if (fAscend[i]) {
|
||||
|
||||
// Lower fade triangle
|
||||
BEGIN_TRIANGLE;
|
||||
LIGHT; glVertex2f(gFanRX[i], gFanRY[i]);
|
||||
DARK; glVertex2f(gFadeIX[i], gFadeIY[i]);
|
||||
DARK; glVertex2f(gFadeRX[i], gFadeRY[i]);
|
||||
END_TRIANGLE;
|
||||
|
||||
// Intermediate fade triangle, if necessary
|
||||
if (gFadeIY[i] != gFadeLY[i+1]) {
|
||||
BEGIN_TRIANGLE;
|
||||
LIGHT; glVertex2f(gFanRX[i], gFanRY[i]);
|
||||
DARK; glVertex2f(gFadeLX[i+1], gFadeLY[i+1]);
|
||||
DARK; glVertex2f(gFadeIX[i], gFadeIY[i]);
|
||||
END_TRIANGLE;
|
||||
}
|
||||
|
||||
// Upper fade triangle
|
||||
BEGIN_TRIANGLE;
|
||||
LIGHT; glVertex2f(gFanRX[i], gFanRY[i]);
|
||||
LIGHT; glVertex2f(gFanLX[i+1], gFanLY[i+1]);
|
||||
DARK; glVertex2f(gFadeLX[i+1], gFadeLY[i+1]);
|
||||
END_TRIANGLE;
|
||||
|
||||
// Descending?
|
||||
} else {
|
||||
|
||||
// Lower fade triangle
|
||||
BEGIN_TRIANGLE;
|
||||
LIGHT; glVertex2f(gFanLX[i+1], gFanLY[i+1]);
|
||||
DARK; glVertex2f(gFadeLX[i+1], gFadeLY[i+1]);
|
||||
DARK; glVertex2f(gFadeIX[i], gFadeIY[i]);
|
||||
END_TRIANGLE;
|
||||
|
||||
// Intermediate fade triangle, if necessary
|
||||
if (gFadeIY[i] != gFadeRY[i]) {
|
||||
BEGIN_TRIANGLE;
|
||||
LIGHT; glVertex2f(gFanLX[i+1], gFanLY[i+1]);
|
||||
DARK; glVertex2f(gFadeIX[i], gFadeIY[i]);
|
||||
DARK; glVertex2f(gFadeRX[i], gFadeRY[i]);
|
||||
END_TRIANGLE;
|
||||
}
|
||||
|
||||
// Upper fade triangle
|
||||
BEGIN_TRIANGLE;
|
||||
LIGHT; glVertex2f(gFanLX[i+1], gFanLY[i+1]);
|
||||
DARK; glVertex2f(gFadeRX[i], gFadeRY[i]);
|
||||
LIGHT; glVertex2f(gFanRX[i], gFanRY[i]);
|
||||
END_TRIANGLE;
|
||||
// Help me! My brain can't program without local function definitions anymore!
|
||||
#define VERTEX(x,y,light) \
|
||||
if(pOnScreen) { \
|
||||
if(light) glColor3f(1.0f, 0.0f, 0.0f); \
|
||||
else glColor3f(0.5f, 0.5f, 0.0f); \
|
||||
} else if(iPass == 0) { \
|
||||
float dx = (x) - gLightX, dy = (y) - gLightY; \
|
||||
float gDist = sqrt(dx*dx+dy*dy); \
|
||||
float gMult = Min(0.5f / pLight->getSize(), 0.5f / gDist); \
|
||||
float gNormX = (0.5f + dx * gMult) / 1.5f / 16.0f; \
|
||||
float gNormY = (0.5f + dy * gMult) / 1.5f / 16.0f; \
|
||||
if(light) glColor3f(0.1f, gNormX, gNormY); \
|
||||
else glColor3f(0.0f, gNormX, gNormY); \
|
||||
} else glColor3f(0.0f, 0.5f/1.5f/16.0f, 0.5f/1.5f/16.0f); \
|
||||
glVertex2f(x,y)
|
||||
#define DARK(x,y) VERTEX(x,y,false)
|
||||
#define LIGHT(x,y) VERTEX(x,y,true)
|
||||
#define BEGIN_TRIANGLE \
|
||||
if(pOnScreen) glBegin(GL_LINE_LOOP)
|
||||
#define END_TRIANGLE \
|
||||
if(pOnScreen) glEnd()
|
||||
|
||||
// Draw the fan
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glBegin(pOnScreen ? GL_LINE_STRIP : GL_TRIANGLE_FAN);
|
||||
if (!pOnScreen) {
|
||||
LIGHT(gLightX, gLightY);
|
||||
}
|
||||
for (i = 0; i < iRayCnt; i++) {
|
||||
if (i == 0 || gFanRX[i-1] != gFanLX[i] || gFanRY[i-1] != gFanLY[i]) {
|
||||
LIGHT(gFanLX[i], gFanLY[i]);
|
||||
}
|
||||
if (gFanLX[i] != gFanRX[i] || gFanLY[i] != gFanRY[i]) {
|
||||
LIGHT(gFanRX[i], gFanRY[i]);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
// Draw the fade
|
||||
glShadeModel(GL_SMOOTH);
|
||||
if(!pOnScreen) glBegin(GL_TRIANGLES);
|
||||
|
||||
for (i = 0; i < iRayCnt; i++) {
|
||||
|
||||
// The quad. Will be empty if fan points match
|
||||
if (gFanLX[i] != gFanRX[i] || gFanLY[i] != gFanRY[i]) {
|
||||
|
||||
// upper triangle
|
||||
BEGIN_TRIANGLE;
|
||||
LIGHT(gFanLX[i], gFanLY[i]);
|
||||
LIGHT(gFanRX[i], gFanRY[i]);
|
||||
DARK(gFadeLX[i], gFadeLY[i]);
|
||||
END_TRIANGLE;
|
||||
|
||||
// lower triangle, if necessary
|
||||
if (gFadeLX[i] != gFadeRX[i] || gFadeLY[i] != gFadeRY[i]) {
|
||||
BEGIN_TRIANGLE;
|
||||
LIGHT(gFanRX[i], gFanRY[i]);
|
||||
DARK(gFadeRX[i], gFadeRY[i]);
|
||||
DARK(gFadeLX[i], gFadeLY[i]);
|
||||
END_TRIANGLE;
|
||||
}
|
||||
}
|
||||
|
||||
// No intermediate fade for last point
|
||||
if (i+1 >= iRayCnt) continue;
|
||||
|
||||
// Ascending?
|
||||
if (fAscend[i]) {
|
||||
|
||||
// Lower fade triangle
|
||||
BEGIN_TRIANGLE;
|
||||
LIGHT(gFanRX[i], gFanRY[i]);
|
||||
DARK(gFadeIX[i], gFadeIY[i]);
|
||||
DARK(gFadeRX[i], gFadeRY[i]);
|
||||
END_TRIANGLE;
|
||||
|
||||
// Intermediate fade triangle, if necessary
|
||||
if (gFadeIY[i] != gFadeLY[i+1]) {
|
||||
BEGIN_TRIANGLE;
|
||||
LIGHT(gFanRX[i], gFanRY[i]);
|
||||
DARK(gFadeLX[i+1], gFadeLY[i+1]);
|
||||
DARK(gFadeIX[i], gFadeIY[i]);
|
||||
END_TRIANGLE;
|
||||
}
|
||||
|
||||
// Upper fade triangle
|
||||
BEGIN_TRIANGLE;
|
||||
LIGHT(gFanRX[i], gFanRY[i]);
|
||||
LIGHT(gFanLX[i+1], gFanLY[i+1]);
|
||||
DARK(gFadeLX[i+1], gFadeLY[i+1]);
|
||||
END_TRIANGLE;
|
||||
|
||||
// Descending?
|
||||
} else {
|
||||
|
||||
// Lower fade triangle
|
||||
BEGIN_TRIANGLE;
|
||||
LIGHT(gFanLX[i+1], gFanLY[i+1]);
|
||||
DARK(gFadeLX[i+1], gFadeLY[i+1]);
|
||||
DARK(gFadeIX[i], gFadeIY[i]);
|
||||
END_TRIANGLE;
|
||||
|
||||
// Intermediate fade triangle, if necessary
|
||||
if (gFadeIY[i] != gFadeRY[i]) {
|
||||
BEGIN_TRIANGLE;
|
||||
LIGHT(gFanLX[i+1], gFanLY[i+1]);
|
||||
DARK(gFadeIX[i], gFadeIY[i]);
|
||||
DARK(gFadeRX[i], gFadeRY[i]);
|
||||
END_TRIANGLE;
|
||||
}
|
||||
|
||||
// Upper fade triangle
|
||||
BEGIN_TRIANGLE;
|
||||
LIGHT(gFanLX[i+1], gFanLY[i+1]);
|
||||
DARK(gFadeRX[i], gFadeRY[i]);
|
||||
LIGHT(gFanRX[i], gFanRY[i]);
|
||||
END_TRIANGLE;
|
||||
|
||||
}
|
||||
}
|
||||
if (!pOnScreen)
|
||||
glEnd(); // GL_TRIANGLES
|
||||
}
|
||||
if (!pOnScreen)
|
||||
glEnd(); // GL_TRIANGLES
|
||||
|
||||
|
||||
delete[] gFanLX;
|
||||
|
||||
// Reset GL state
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "C4Rect.h"
|
||||
#include "C4Surface.h"
|
||||
#include "C4DrawGL.h"
|
||||
|
||||
class C4FoW
|
||||
{
|
||||
|
@ -14,6 +15,8 @@ private:
|
|||
class C4FoWLight *pLights;
|
||||
|
||||
public:
|
||||
void Clear();
|
||||
|
||||
void Add(C4Object *pObj);
|
||||
void Remove(C4Object *pObj);
|
||||
void Update(C4Rect r);
|
||||
|
@ -25,11 +28,12 @@ public:
|
|||
class C4FoWRegion
|
||||
{
|
||||
public:
|
||||
C4FoWRegion(C4FoW *pFoW);
|
||||
C4FoWRegion(C4FoW *pFoW, C4Player *pPlayer);
|
||||
~C4FoWRegion();
|
||||
|
||||
private:
|
||||
C4FoW *pFoW;
|
||||
C4Player *pPlayer;
|
||||
C4Rect Region, OldRegion;
|
||||
C4Surface *pSurface, *pBackSurface;
|
||||
GLuint hFrameBufDraw, hFrameBufRead;
|
||||
|
@ -39,12 +43,14 @@ public:
|
|||
const C4Surface *getSurface() const { return pSurface; }
|
||||
const C4Surface *getBackSurface() const { return pBackSurface; }
|
||||
|
||||
bool Create();
|
||||
void Clear();
|
||||
|
||||
void Set(C4Rect r) { Region = r; }
|
||||
void Update(C4Rect r);
|
||||
void Render(const C4TargetFacet *pOnScreen = NULL);
|
||||
|
||||
private:
|
||||
bool BindFramebuf();
|
||||
|
||||
};
|
||||
|
||||
class C4FoWLight
|
||||
|
|
|
@ -1451,6 +1451,7 @@ void C4Landscape::Default()
|
|||
delete [] BridgeMatConversion[i];
|
||||
BridgeMatConversion[i] = NULL;
|
||||
}
|
||||
delete pFoW; pFoW = NULL;
|
||||
}
|
||||
|
||||
void C4Landscape::ClearMatCount()
|
||||
|
|
|
@ -170,8 +170,9 @@ bool C4LandscapeRenderGL::InitMaterialTexture(C4TextureMap *pTexs)
|
|||
|
||||
// Determine depth to use
|
||||
iMaterialTextureDepth = 1;
|
||||
while(iMaterialTextureDepth < int32_t(MaterialTextureMap.size()))
|
||||
while(iMaterialTextureDepth < 2*int32_t(MaterialTextureMap.size()))
|
||||
iMaterialTextureDepth <<= 1;
|
||||
int32_t iNormalDepth = iMaterialTextureDepth / 2;
|
||||
|
||||
// Find the largest texture
|
||||
C4Texture *pTex, *pRefTex; C4Surface *pRefSfc = NULL;
|
||||
|
@ -207,14 +208,15 @@ bool C4LandscapeRenderGL::InitMaterialTexture(C4TextureMap *pTexs)
|
|||
{
|
||||
BYTE *p = pData + i * iTexSize;
|
||||
// Get texture at position
|
||||
const char *szTexture;
|
||||
StdStrBuf Texture;
|
||||
bool fNormal = i >= iNormalDepth;
|
||||
if(i < int32_t(MaterialTextureMap.size()))
|
||||
szTexture = MaterialTextureMap[i].getData();
|
||||
else
|
||||
szTexture = "";
|
||||
Texture.Ref(MaterialTextureMap[i]);
|
||||
else if(fNormal && i < iNormalDepth + int32_t(MaterialTextureMap.size()))
|
||||
Texture.Format("%s_NRM", MaterialTextureMap[i-iNormalDepth].getData());
|
||||
// Try to find the texture
|
||||
C4Texture *pTex; C4Surface *pSurface;
|
||||
if((pTex = pTexs->GetTexture(szTexture)) && (pSurface = pTex->Surface32))
|
||||
if((pTex = pTexs->GetTexture(Texture.getData())) && (pSurface = pTex->Surface32))
|
||||
{
|
||||
#ifdef DEBUG_SOLID_COLOR_TEXTURES
|
||||
// Just write a solid color that depends on the texture index
|
||||
|
@ -230,7 +232,7 @@ bool C4LandscapeRenderGL::InitMaterialTexture(C4TextureMap *pTexs)
|
|||
{
|
||||
// Size recheck
|
||||
if(pSurface->Wdt != iTexWdt || pSurface->Hgt != iTexHgt)
|
||||
LogF(" gl: texture %s size mismatch (%dx%d vs %dx%d)!", szTexture, pSurface->Wdt, pSurface->Hgt, iTexWdt, iTexHgt);
|
||||
LogF(" gl: texture %s size mismatch (%dx%d vs %dx%d)!", Texture.getData(), pSurface->Wdt, pSurface->Hgt, iTexWdt, iTexHgt);
|
||||
// Copy bytes
|
||||
DWORD *texdata = reinterpret_cast<DWORD *>(p);
|
||||
pSurface->Lock();
|
||||
|
@ -243,7 +245,7 @@ bool C4LandscapeRenderGL::InitMaterialTexture(C4TextureMap *pTexs)
|
|||
#endif
|
||||
}
|
||||
// Seperator texture?
|
||||
if(SEqual(szTexture, SEPERATOR_TEXTURE))
|
||||
if(SEqual(Texture.getData(), SEPERATOR_TEXTURE))
|
||||
{
|
||||
// Make some ugly stripes
|
||||
DWORD *texdata = reinterpret_cast<DWORD *>(p);
|
||||
|
@ -252,8 +254,9 @@ bool C4LandscapeRenderGL::InitMaterialTexture(C4TextureMap *pTexs)
|
|||
*texdata++ = ((x + y) % 32 < 16 ? RGBA(255, 0, 0, 255) : RGBA(0, 255, 255, 255));
|
||||
continue;
|
||||
}
|
||||
// If we didn't "continue" yet, we haven't written the texture yet. Make it transparent.
|
||||
memset(p, 0, iTexSize);
|
||||
// If we didn't "continue" yet, we haven't written the texture yet.
|
||||
// Make color texture transparent, and normal texture flat.
|
||||
memset(p, fNormal ? 127 : 0, iTexSize);
|
||||
}
|
||||
|
||||
// Clear error error(s?)
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
|
||||
C4Texture::C4Texture()
|
||||
{
|
||||
Name[0]=0;
|
||||
Surface32=NULL;
|
||||
AvgColor = 0x00000000;
|
||||
Next=NULL;
|
||||
|
@ -134,7 +133,7 @@ bool C4TextureMap::AddTexture(const char *szTexture, C4Surface * sfcSurface)
|
|||
{
|
||||
C4Texture *pTexture;
|
||||
if (!(pTexture=new C4Texture)) return false;
|
||||
SCopy(szTexture,pTexture->Name,C4M_MaxName);
|
||||
pTexture->Name.Copy(szTexture);
|
||||
pTexture->Surface32=sfcSurface;
|
||||
pTexture->Next=FirstTexture;
|
||||
FirstTexture=pTexture;
|
||||
|
@ -379,7 +378,7 @@ C4Texture * C4TextureMap::GetTexture(const char *szTexture)
|
|||
{
|
||||
C4Texture *pTexture;
|
||||
for (pTexture=FirstTexture; pTexture; pTexture=pTexture->Next)
|
||||
if (SEqualNoCase(pTexture->Name,szTexture))
|
||||
if (SEqualNoCase(pTexture->Name.getData(),szTexture))
|
||||
return pTexture;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -389,7 +388,7 @@ int32_t C4TextureMap::GetTextureIndex(const char *szName)
|
|||
C4Texture *pTexture;
|
||||
int32_t i=0;
|
||||
for (pTexture=FirstTexture; pTexture; pTexture=pTexture->Next, i++)
|
||||
if (SEqualNoCase(pTexture->Name,szName))
|
||||
if (SEqualNoCase(pTexture->Name.getData(),szName))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
@ -398,7 +397,7 @@ bool C4TextureMap::CheckTexture(const char *szTexture)
|
|||
{
|
||||
C4Texture *pTexture;
|
||||
for (pTexture=FirstTexture; pTexture; pTexture=pTexture->Next)
|
||||
if (SEqualNoCase(pTexture->Name,szTexture))
|
||||
if (SEqualNoCase(pTexture->Name.getData(),szTexture))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -409,7 +408,7 @@ const char* C4TextureMap::GetTexture(int32_t iIndex)
|
|||
int32_t cindex;
|
||||
for (pTexture=FirstTexture,cindex=0; pTexture; pTexture=pTexture->Next,cindex++)
|
||||
if (cindex==iIndex)
|
||||
return pTexture->Name;
|
||||
return pTexture->Name.getData();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
|
||||
uint32_t GetAverageColor() const { return AvgColor; }
|
||||
protected:
|
||||
char Name[C4M_MaxName+1];
|
||||
StdStrBuf Name;
|
||||
uint32_t AvgColor;
|
||||
C4Texture *Next;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue