# Initial work on fancy water.
Also, horizon height (skybox vertical offset) can now be set from the console with renderer.horizonHeight. This was SVN commit r3893.
This commit is contained in:
parent
965b4c9f92
commit
f0615df318
@ -158,7 +158,7 @@ extern LibError LDR_NonprogressiveLoad();
|
||||
#define LDR_CHECK_TIMEOUT(completed_jobs, total_jobs)\
|
||||
if(get_time() > end_time)\
|
||||
{\
|
||||
int progress_percent = (completed_jobs*100 / total_jobs);\
|
||||
int progress_percent = ((completed_jobs)*100 / (total_jobs));\
|
||||
/* 0 means "finished", so don't return that! */\
|
||||
if(progress_percent == 0)\
|
||||
progress_percent = 1;\
|
||||
|
@ -1469,6 +1469,21 @@ void CRenderer::JSI_SetSky(JSContext* ctx, jsval newval)
|
||||
m->skyManager.SetSkySet(skySet);
|
||||
}
|
||||
|
||||
jsval CRenderer::JSI_GetHorizonHeight(JSContext*)
|
||||
{
|
||||
return ToJSVal(m->skyManager.m_HorizonHeight);
|
||||
}
|
||||
|
||||
void CRenderer::JSI_SetHorizonHeight(JSContext* ctx, jsval newval)
|
||||
{
|
||||
float value;
|
||||
|
||||
if (!ToPrimitive<float>(ctx, newval, value))
|
||||
return;
|
||||
|
||||
m->skyManager.m_HorizonHeight = value;
|
||||
}
|
||||
|
||||
void CRenderer::ScriptingInit()
|
||||
{
|
||||
AddProperty(L"fastPlayerColor", &CRenderer::JSI_GetFastPlayerColor, &CRenderer::JSI_SetFastPlayerColor);
|
||||
@ -1481,6 +1496,7 @@ void CRenderer::ScriptingInit()
|
||||
AddProperty(L"disableCopyShadow", &CRenderer::m_DisableCopyShadow);
|
||||
AddProperty(L"depthTextureBits", &CRenderer::JSI_GetDepthTextureBits, &CRenderer::JSI_SetDepthTextureBits);
|
||||
AddProperty(L"skySet", &CRenderer::JSI_GetSky, &CRenderer::JSI_SetSky);
|
||||
AddProperty(L"horizonHeight", &CRenderer::JSI_GetHorizonHeight, &CRenderer::JSI_SetHorizonHeight);
|
||||
|
||||
CJSObject<CRenderer>::ScriptingInit("Renderer");
|
||||
}
|
||||
|
@ -331,6 +331,8 @@ protected:
|
||||
void JSI_SetDepthTextureBits(JSContext* ctx, jsval newval);
|
||||
jsval JSI_GetSky(JSContext*);
|
||||
void JSI_SetSky(JSContext* ctx, jsval newval);
|
||||
jsval JSI_GetHorizonHeight(JSContext*);
|
||||
void JSI_SetHorizonHeight(JSContext* ctx, jsval newval);
|
||||
static void ScriptingInit();
|
||||
|
||||
// patch rendering stuff
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "lib/res/graphics/tex.h"
|
||||
#include "lib/res/graphics/ogl_tex.h"
|
||||
|
||||
#include "maths/MathUtil.h"
|
||||
|
||||
#include "ps/CLogger.h"
|
||||
#include "ps/Loader.h"
|
||||
|
||||
@ -22,6 +24,7 @@
|
||||
#include "renderer/Renderer.h"
|
||||
|
||||
#include "graphics/Camera.h"
|
||||
#include "graphics/LightEnv.h"
|
||||
|
||||
#define LOG_CATEGORY "graphics"
|
||||
|
||||
@ -50,6 +53,8 @@ SkyManager::SkyManager()
|
||||
// TODO: add a way to set the initial skyset before progressive load
|
||||
m_SkySet = L"default";
|
||||
|
||||
m_HorizonHeight = 0;
|
||||
|
||||
for (uint i = 0; i < ARRAY_SIZE(m_SkyTexture); i++)
|
||||
m_SkyTexture[i] = 0;
|
||||
|
||||
@ -155,11 +160,15 @@ void SkyManager::RenderSky()
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
||||
// Translate so we are at the camera in the X and Z directions,
|
||||
// but put the horizon at Y=0 so it looks right when the camera is higher
|
||||
// Translate so we are at the camera in the X and Z directions, but
|
||||
// put the horizon at a fixed height regardless of camera Y
|
||||
const CCamera& camera = g_Renderer.GetViewCamera();
|
||||
CVector3D pos = camera.m_Orientation.GetTranslation();
|
||||
glTranslatef( pos.X, 0.0f, pos.Z );
|
||||
glTranslatef( pos.X, m_HorizonHeight, pos.Z );
|
||||
|
||||
// Rotate so that the "left" face, which contains the brightest part of each
|
||||
// skymap, is in the direction of the sun from our light environment
|
||||
glRotatef( 90.0f + g_Renderer.GetLightEnv().GetRotation()*180.0f/M_PI, 0.0f, 1.0f, 0.0f );
|
||||
|
||||
// Distance to draw the faces at
|
||||
const float D = 2000.0;
|
||||
|
@ -20,6 +20,7 @@ class SkyManager
|
||||
{
|
||||
public:
|
||||
bool m_RenderSky;
|
||||
float m_HorizonHeight;
|
||||
|
||||
public:
|
||||
SkyManager();
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "renderer/TerrainRenderer.h"
|
||||
#include "renderer/WaterManager.h"
|
||||
|
||||
#include "lib/res/graphics/ogl_shader.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TerrainRenderer implementation
|
||||
@ -59,6 +61,9 @@ struct TerrainRendererInternals
|
||||
* @todo Merge this list with CPatchRData list
|
||||
*/
|
||||
std::vector<CPatch*> visiblePatches;
|
||||
|
||||
/// Fancy water shader
|
||||
Handle fancyWaterShader;
|
||||
};
|
||||
|
||||
|
||||
@ -69,10 +74,15 @@ TerrainRenderer::TerrainRenderer()
|
||||
{
|
||||
m = new TerrainRendererInternals();
|
||||
m->phase = Phase_Submit;
|
||||
m->fancyWaterShader = 0;
|
||||
}
|
||||
|
||||
TerrainRenderer::~TerrainRenderer()
|
||||
{
|
||||
if( m->fancyWaterShader )
|
||||
{
|
||||
ogl_program_free( m->fancyWaterShader );
|
||||
}
|
||||
delete m;
|
||||
}
|
||||
|
||||
@ -375,6 +385,14 @@ void TerrainRenderer::RenderWater()
|
||||
{
|
||||
PROFILE( "render water" );
|
||||
|
||||
bool fancy = g_Renderer.m_Options.m_FancyWater;
|
||||
|
||||
// If we're using fancy water, make sure its shader is loaded
|
||||
if(fancy && !m->fancyWaterShader)
|
||||
{
|
||||
m->fancyWaterShader = ogl_program_load( "shaders/water_high.xml" );
|
||||
//debug_printf("Loaded the water shader!!\n");
|
||||
}
|
||||
|
||||
//(Crappy) fresnel effect
|
||||
CCamera* Camera=g_Game->GetView()->GetCamera();
|
||||
@ -384,15 +402,11 @@ void TerrainRenderer::RenderWater()
|
||||
//Invert and set boundaries
|
||||
FresnelScalar = (1 - FresnelScalar) * 0.4f + 0.6f;
|
||||
|
||||
const int DX[] = {1,1,0,0};
|
||||
const int DZ[] = {0,1,1,0};
|
||||
|
||||
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
|
||||
int mapSize = terrain->GetVerticesPerSide();
|
||||
CLOSManager* losMgr = g_Game->GetWorld()->GetLOSManager();
|
||||
WaterManager* WaterMgr = g_Renderer.GetWaterManager();
|
||||
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDepthMask(GL_FALSE);
|
||||
@ -401,27 +415,90 @@ void TerrainRenderer::RenderWater()
|
||||
|
||||
double period = 1.6;
|
||||
int curTex = (int)(time*60/period) % 60;
|
||||
ogl_tex_bind(WaterMgr->m_WaterTexture[curTex], 0);
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
float tx = -fmod(time, 20.0)/20.0;
|
||||
float ty = fmod(time, 35.0)/35.0;
|
||||
glTranslatef(tx, ty, 0);
|
||||
if(fancy)
|
||||
{
|
||||
ogl_tex_bind(WaterMgr->m_NormalMap[curTex], 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ogl_tex_bind(WaterMgr->m_WaterTexture[curTex], 0);
|
||||
}
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
||||
if(!fancy)
|
||||
{
|
||||
// Shift the texture coordinates to make it "flow"
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
float tx = -fmod(time, 20.0)/20.0;
|
||||
float ty = fmod(time, 35.0)/35.0;
|
||||
glTranslatef(tx, ty, 0);
|
||||
}
|
||||
|
||||
if(!fancy)
|
||||
{
|
||||
// Set up texture environment to multiply vertex RGB by texture RGB and use vertex alpha
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Temp stuff for testing
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
||||
}
|
||||
|
||||
// Set the proper LOD bias
|
||||
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
|
||||
|
||||
// Some offsets used to go around counterclockwise while keeping code concise
|
||||
const int DX[] = {1,1,0,0};
|
||||
const int DZ[] = {0,1,1,0};
|
||||
|
||||
GLint vertexDepth = 0; // water depth attribute, if using fancy water
|
||||
|
||||
if(fancy)
|
||||
{
|
||||
ogl_program_use( m->fancyWaterShader );
|
||||
|
||||
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
|
||||
//SetAmbient(lightenv.m_TerrainAmbientColor);
|
||||
//SetSunDir(lightenv.GetSunDir());
|
||||
//SetSunColor(lightenv.m_SunColor);
|
||||
|
||||
GLint ambient = ogl_program_get_uniform_location( m->fancyWaterShader, "ambient" );
|
||||
GLint sunDir = ogl_program_get_uniform_location( m->fancyWaterShader, "sunDir" );
|
||||
GLint sunColor = ogl_program_get_uniform_location( m->fancyWaterShader, "sunColor" );
|
||||
GLint shininess = ogl_program_get_uniform_location( m->fancyWaterShader, "shininess" );
|
||||
GLint cameraPos = ogl_program_get_uniform_location( m->fancyWaterShader, "cameraPos" );
|
||||
GLint normalMap = ogl_program_get_uniform_location( m->fancyWaterShader, "normalMap" );
|
||||
|
||||
pglUniform3fvARB( ambient, 1, &lightEnv.m_TerrainAmbientColor.X );
|
||||
pglUniform3fvARB( sunDir, 1, &lightEnv.GetSunDir().X );
|
||||
pglUniform3fvARB( sunColor, 1, &lightEnv.m_SunColor.X );
|
||||
pglUniform1fARB( shininess, 200.0f );
|
||||
pglUniform1iARB( normalMap, 0 ); // texture unit 0
|
||||
|
||||
const CCamera& camera = g_Renderer.GetViewCamera();
|
||||
CVector3D camPos = camera.m_Orientation.GetTranslation();
|
||||
pglUniform3fvARB( cameraPos, 1, &camPos.X );
|
||||
|
||||
vertexDepth = ogl_program_get_attrib_location( m->fancyWaterShader, "vertexDepth" );
|
||||
}
|
||||
|
||||
float repeatFreq = (fancy ? 10.0f : 16.0f);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
for(size_t i=0; i<m->visiblePatches.size(); i++)
|
||||
@ -481,8 +558,13 @@ void TerrainRenderer::RenderWater()
|
||||
}
|
||||
}
|
||||
|
||||
if(fancy)
|
||||
{
|
||||
pglVertexAttrib1fARB( vertexDepth, WaterMgr->m_WaterHeight - terrainHeight );
|
||||
}
|
||||
|
||||
glColor4f(WaterMgr->m_WaterColor.r*losMod, WaterMgr->m_WaterColor.g*losMod, WaterMgr->m_WaterColor.b*losMod, alpha * FresnelScalar);
|
||||
pglMultiTexCoord2fARB(GL_TEXTURE0, vertX/16.0f, vertZ/16.0f);
|
||||
pglMultiTexCoord2fARB(GL_TEXTURE0, vertX/repeatFreq, vertZ/repeatFreq);
|
||||
glVertex3f(vertX, WaterMgr->m_WaterHeight, vertZ);
|
||||
}
|
||||
} //end of x loop
|
||||
@ -490,6 +572,11 @@ void TerrainRenderer::RenderWater()
|
||||
}
|
||||
glEnd();
|
||||
|
||||
if(fancy)
|
||||
{
|
||||
ogl_program_use( 0 );
|
||||
}
|
||||
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
@ -50,7 +50,11 @@ WaterManager::WaterManager()
|
||||
for (uint i = 0; i < ARRAY_SIZE(m_WaterTexture); i++)
|
||||
m_WaterTexture[i] = 0;
|
||||
|
||||
for (uint i = 0; i < ARRAY_SIZE(m_NormalMap); i++)
|
||||
m_NormalMap[i] = 0;
|
||||
|
||||
cur_loading_water_tex = 0;
|
||||
cur_loading_normal_map = 0;
|
||||
}
|
||||
|
||||
WaterManager::~WaterManager()
|
||||
@ -65,29 +69,48 @@ WaterManager::~WaterManager()
|
||||
int WaterManager::LoadWaterTextures()
|
||||
{
|
||||
const uint num_textures = ARRAY_SIZE(m_WaterTexture);
|
||||
const uint num_normal_maps = ARRAY_SIZE(m_NormalMap);
|
||||
|
||||
// TODO: add a member variable and setter for this. (can't make this
|
||||
// a parameter because this function is called via delay-load code)
|
||||
static const char* const water_type = "default";
|
||||
|
||||
// yield after this time is reached. balances increased progress bar
|
||||
// smoothness vs. slowing down loading.
|
||||
const double end_time = get_time() + 100e-3;
|
||||
|
||||
char filename[PATH_MAX];
|
||||
|
||||
while (cur_loading_water_tex < num_textures)
|
||||
{
|
||||
char waterName[PATH_MAX];
|
||||
// TODO: add a member variable and setter for this. (can't make this
|
||||
// a parameter because this function is called via delay-load code)
|
||||
static const char* const water_type = "animation2";
|
||||
snprintf(waterName, ARRAY_SIZE(waterName), "art/textures/terrain/types/water/%s/water%02d.dds", water_type, cur_loading_water_tex+1);
|
||||
Handle ht = ogl_tex_load(waterName);
|
||||
snprintf(filename, ARRAY_SIZE(filename), "art/textures/animated/water/%s/diffuse%02d.dds",
|
||||
water_type, cur_loading_water_tex+1);
|
||||
Handle ht = ogl_tex_load(filename);
|
||||
if (ht <= 0)
|
||||
{
|
||||
LOG(ERROR, LOG_CATEGORY, "LoadWaterTextures failed on \"%s\"", waterName);
|
||||
LOG(ERROR, LOG_CATEGORY, "LoadWaterTextures failed on \"%s\"", filename);
|
||||
return ht;
|
||||
}
|
||||
m_WaterTexture[cur_loading_water_tex] = ht;
|
||||
RETURN_ERR(ogl_tex_upload(ht));
|
||||
|
||||
cur_loading_water_tex++;
|
||||
LDR_CHECK_TIMEOUT(cur_loading_water_tex, num_textures);
|
||||
LDR_CHECK_TIMEOUT(cur_loading_water_tex, num_textures + num_normal_maps);
|
||||
}
|
||||
|
||||
while (cur_loading_normal_map < num_normal_maps)
|
||||
{
|
||||
snprintf(filename, ARRAY_SIZE(filename), "art/textures/animated/water/%s/normal%02d.dds",
|
||||
water_type, cur_loading_normal_map+1);
|
||||
Handle ht = ogl_tex_load(filename);
|
||||
if (ht <= 0)
|
||||
{
|
||||
LOG(ERROR, LOG_CATEGORY, "LoadWaterTextures failed on \"%s\"", filename);
|
||||
return ht;
|
||||
}
|
||||
m_NormalMap[cur_loading_normal_map] = ht;
|
||||
RETURN_ERR(ogl_tex_upload(ht));
|
||||
cur_loading_normal_map++;
|
||||
LDR_CHECK_TIMEOUT(num_textures + cur_loading_normal_map, num_textures + num_normal_maps);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -103,5 +126,14 @@ void WaterManager::UnloadWaterTextures()
|
||||
ogl_tex_free(m_WaterTexture[i]);
|
||||
m_WaterTexture[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
for(uint i = 0; i < ARRAY_SIZE(m_NormalMap); i++)
|
||||
{
|
||||
ogl_tex_free(m_NormalMap[i]);
|
||||
m_NormalMap[i] = 0;
|
||||
}
|
||||
|
||||
cur_loading_water_tex = 0; // so they will be reloaded if LoadWaterTextures is called again
|
||||
cur_loading_normal_map = 0;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ class WaterManager
|
||||
{
|
||||
public:
|
||||
Handle m_WaterTexture[60];
|
||||
Handle m_NormalMap[60];
|
||||
int m_WaterCurrentTex;
|
||||
CColor m_WaterColor;
|
||||
bool m_RenderWater;
|
||||
@ -62,6 +63,7 @@ public:
|
||||
private:
|
||||
/// State of progressive loading (in # of loaded textures)
|
||||
uint cur_loading_water_tex;
|
||||
uint cur_loading_normal_map;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user