mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2025-02-18 10:15:38 +00:00
Rewrite the spot light code, and implement the missing fog logic. (HarryTuttle)
This commit is contained in:
parent
07660be0df
commit
f0e00c5dc7
|
@ -137,11 +137,13 @@ struct Viewport
|
||||||
float spotEllipse[4]; // spotlight ellipse (see RenderViewport())
|
float spotEllipse[4]; // spotlight ellipse (see RenderViewport())
|
||||||
float spotRange[2]; // Z range
|
float spotRange[2]; // Z range
|
||||||
float spotColor[3]; // color
|
float spotColor[3]; // color
|
||||||
float fogParams[5]; // fog parameters (...)
|
float fogParams[7]; // fog parameters (...)
|
||||||
float scrollFog; // a transparency value that determines if fog is blended over the bottom 2D layer
|
float scrollFog; // a transparency value that determines if fog is blended over the bottom 2D layer
|
||||||
int x, y; // viewport coordinates (scaled and in OpenGL format)
|
int x, y; // viewport coordinates (scaled and in OpenGL format)
|
||||||
int width, height; // viewport dimensions (scaled for display surface size)
|
int width, height; // viewport dimensions (scaled for display surface size)
|
||||||
int priority;
|
int priority;
|
||||||
|
float spotFogColor[3]; // spotlight color on fog
|
||||||
|
float scrollAtt;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Clip { INSIDE, OUTSIDE, INTERCEPT, NOT_SET };
|
enum class Clip { INSIDE, OUTSIDE, INTERCEPT, NOT_SET };
|
||||||
|
|
|
@ -97,15 +97,24 @@ void CNew3D::UploadTextures(unsigned level, unsigned x, unsigned y, unsigned wid
|
||||||
|
|
||||||
void CNew3D::DrawScrollFog()
|
void CNew3D::DrawScrollFog()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// the logic for this is still not quite right
|
||||||
|
// the sroll fog value seems to be set with multiple viewports.. currently unknown which one to use
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
|
|
||||||
for (auto &n : m_nodes) {
|
for (auto &n : m_nodes) {
|
||||||
|
|
||||||
if (n.viewport.scrollFog > 0 && n.viewport.priority == i) {
|
if (n.viewport.scrollFog > 0 && n.viewport.priority == i) {
|
||||||
|
|
||||||
float *rgb = n.viewport.fogParams;
|
float rgba[4] = {n.viewport.fogParams[0], n.viewport.fogParams[1], n.viewport.fogParams[2], n.viewport.scrollFog};
|
||||||
|
float attenuation = n.viewport.scrollAtt; // Seems to pass the wrong values!
|
||||||
|
float ambient = n.viewport.fogParams[6];
|
||||||
|
float *spotRGB = n.viewport.spotFogColor;
|
||||||
|
float *spotEllipse = n.viewport.spotEllipse;
|
||||||
|
|
||||||
glViewport(0, 0, m_totalXRes, m_totalYRes); // fill the whole viewport
|
glViewport(0, 0, m_totalXRes, m_totalYRes); // fill the whole viewport
|
||||||
m_r3dScrollFog.DrawScrollFog(rgb[0], rgb[1], rgb[2], n.viewport.scrollFog);
|
m_r3dScrollFog.DrawScrollFog(rgba, attenuation, ambient, spotRGB, spotEllipse);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,27 +761,36 @@ void CNew3D::RenderViewport(UINT32 addr)
|
||||||
|
|
||||||
// Spotlight
|
// Spotlight
|
||||||
int spotColorIdx = (vpnode[0x20] >> 11) & 7; // spotlight color index
|
int spotColorIdx = (vpnode[0x20] >> 11) & 7; // spotlight color index
|
||||||
vp->spotEllipse[0] = (float)((vpnode[0x1E] >> 3) & 0x1FFF); // spotlight X position (fractional component?)
|
int spotFogColorIdx = (vpnode[0x20] >> 8) & 7; // spotlight on fog color index
|
||||||
vp->spotEllipse[1] = (float)((vpnode[0x1D] >> 3) & 0x1FFF); // spotlight Y
|
vp->spotEllipse[0] = (float)(INT16)(vpnode[0x1E] & 0xFFFF) / 8.0f; // spotlight X position (13.3 fixed point)
|
||||||
vp->spotEllipse[2] = (float)((vpnode[0x1E] >> 16) & 0xFFFF); // spotlight X size (16-bit? May have fractional component below bit 16)
|
vp->spotEllipse[1] = (float)(INT16)(vpnode[0x1D] & 0xFFFF) / 8.0f; // spotlight Y
|
||||||
|
vp->spotEllipse[2] = (float)((vpnode[0x1E] >> 16) & 0xFFFF); // spotlight X size (16-bit)
|
||||||
vp->spotEllipse[3] = (float)((vpnode[0x1D] >> 16) & 0xFFFF); // spotlight Y size
|
vp->spotEllipse[3] = (float)((vpnode[0x1D] >> 16) & 0xFFFF); // spotlight Y size
|
||||||
|
|
||||||
vp->spotRange[0] = 1.0f / (*(float *)&vpnode[0x21]); // spotlight start
|
vp->spotRange[0] = 1.0f / (*(float *)&vpnode[0x21]); // spotlight start
|
||||||
vp->spotRange[1] = *(float *)&vpnode[0x1F]; // spotlight extent
|
vp->spotRange[1] = *(float *)&vpnode[0x1F]; // spotlight extent
|
||||||
|
|
||||||
if (vp->spotRange[1] == 0) { // if light extent = 0 light is effectively disabled
|
// Star Wars Trilogy needs this
|
||||||
spotColorIdx = 0;
|
vp->spotRange[0] = std::min(vp->spotRange[0], std::numeric_limits<float>::max());
|
||||||
}
|
vp->spotRange[0] = std::max(vp->spotRange[0], std::numeric_limits<float>::lowest());
|
||||||
|
|
||||||
vp->spotColor[0] = color[spotColorIdx][0]; // spotlight color
|
vp->spotColor[0] = color[spotColorIdx][0]; // spotlight color
|
||||||
vp->spotColor[1] = color[spotColorIdx][1];
|
vp->spotColor[1] = color[spotColorIdx][1];
|
||||||
vp->spotColor[2] = color[spotColorIdx][2];
|
vp->spotColor[2] = color[spotColorIdx][2];
|
||||||
|
|
||||||
// Spotlight is applied on a per pixel basis, must scale its position and size to screen
|
vp->spotFogColor[0] = color[spotFogColorIdx][0]; // spotlight color on fog
|
||||||
vp->spotEllipse[1] = 384.0f - vp->spotEllipse[1];
|
vp->spotFogColor[1] = color[spotFogColorIdx][1];
|
||||||
vp->spotRange[1] += vp->spotRange[0]; // limit
|
vp->spotFogColor[2] = color[spotFogColorIdx][2];
|
||||||
vp->spotEllipse[2] = 496.0f / sqrt(vp->spotEllipse[2]); // spotlight appears to be specified in terms of physical resolution (unconfirmed)
|
|
||||||
vp->spotEllipse[3] = 384.0f / sqrt(vp->spotEllipse[3]);
|
// spotlight is specified in terms of physical resolution
|
||||||
|
vp->spotEllipse[1] = 384.0f - vp->spotEllipse[1]; // flip Y position
|
||||||
|
|
||||||
|
// Avoid division by zero
|
||||||
|
vp->spotEllipse[2] = std::max(1.0f, vp->spotEllipse[2]);
|
||||||
|
vp->spotEllipse[3] = std::max(1.0f, vp->spotEllipse[3]);
|
||||||
|
|
||||||
|
vp->spotEllipse[2] = std::roundf(2047.0f / vp->spotEllipse[2]);
|
||||||
|
vp->spotEllipse[3] = std::roundf(2047.0f / vp->spotEllipse[3]);
|
||||||
|
|
||||||
// Scale the spotlight to the OpenGL viewport
|
// Scale the spotlight to the OpenGL viewport
|
||||||
vp->spotEllipse[0] = vp->spotEllipse[0] * m_xRatio + m_xOffs;
|
vp->spotEllipse[0] = vp->spotEllipse[0] * m_xRatio + m_xOffs;
|
||||||
|
@ -787,30 +805,16 @@ void CNew3D::RenderViewport(UINT32 addr)
|
||||||
vp->fogParams[3] = std::abs(*(float *)&vpnode[0x23]); // fog density - ocean hunter uses negative values, but looks the same
|
vp->fogParams[3] = std::abs(*(float *)&vpnode[0x23]); // fog density - ocean hunter uses negative values, but looks the same
|
||||||
vp->fogParams[4] = (float)(INT16)(vpnode[0x25] & 0xFFFF)*(1.0f / 255.0f); // fog start
|
vp->fogParams[4] = (float)(INT16)(vpnode[0x25] & 0xFFFF)*(1.0f / 255.0f); // fog start
|
||||||
|
|
||||||
|
// Avoid Infinite and NaN values for Star Wars Trilogy
|
||||||
|
if (std::isinf(vp->fogParams[3]) || std::isnan(vp->fogParams[3])) {
|
||||||
|
for (int i = 0; i < 7; i++) vp->fogParams[i] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
vp->fogParams[5] = (float)((vpnode[0x24] >> 16) & 0xFF) * (1.0f / 255.0f); // fog attenuation
|
||||||
|
vp->fogParams[6] = (float)((vpnode[0x25] >> 16) & 0xFF) * (1.0f / 255.0f); // fog ambient
|
||||||
|
|
||||||
vp->scrollFog = (float)(vpnode[0x20] & 0xFF) * (1.0f / 255.0f); // scroll fog
|
vp->scrollFog = (float)(vpnode[0x20] & 0xFF) * (1.0f / 255.0f); // scroll fog
|
||||||
|
vp->scrollAtt = (float)(vpnode[0x24] & 0xFF) * (1.0f / 255.0f); // scroll attenuation
|
||||||
// Unknown light/fog parameters
|
|
||||||
float scrollAtt = (float)(vpnode[0x24] & 0xFF) * (1.0f / 255.0f); // scroll attenuation
|
|
||||||
|
|
||||||
{
|
|
||||||
//test fog paramaters
|
|
||||||
float lightFogColour[3];
|
|
||||||
int fogColourIdx;
|
|
||||||
|
|
||||||
fogColourIdx = (vpnode[0x20] >> 8) & 7;
|
|
||||||
|
|
||||||
lightFogColour[0] = color[fogColourIdx][0];
|
|
||||||
lightFogColour[1] = color[fogColourIdx][1];
|
|
||||||
lightFogColour[2] = color[fogColourIdx][2];
|
|
||||||
|
|
||||||
float fogAttenuation = ((vpnode[0x24] >> 16) & 0xFF) / 255.f;
|
|
||||||
float fogAmbient = ((vpnode[0x25] >> 16) & 0xFF) / 255.f;
|
|
||||||
int debug = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std::isinf(vp->fogParams[3]) || std::isnan(vp->fogParams[3]) || std::isinf(vp->fogParams[4]) || std::isnan(vp->fogParams[4])) { // Star Wars Trilogy
|
|
||||||
vp->fogParams[3] = vp->fogParams[4] = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear texture offsets before proceeding
|
// Clear texture offsets before proceeding
|
||||||
m_nodeAttribs.Reset();
|
m_nodeAttribs.Reset();
|
||||||
|
|
|
@ -12,17 +12,49 @@ static const char *vertexShaderFog =
|
||||||
"{\n"
|
"{\n"
|
||||||
"gl_Position = mvp * gl_Vertex;\n"
|
"gl_Position = mvp * gl_Vertex;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
static const char *fragmentShaderFog =
|
static const char *fragmentShaderFog =
|
||||||
|
|
||||||
"uniform vec4 fogColour;\n"
|
"uniform float fogAttenuation;\n"
|
||||||
|
"uniform float fogAmbient;\n"
|
||||||
"void main()\n"
|
"uniform vec4 fogColour;\n"
|
||||||
"{\n"
|
"uniform vec3 spotFogColor;\n"
|
||||||
"gl_FragColor = fogColour;\n"
|
"uniform vec4 spotEllipse;\n"
|
||||||
"}\n";
|
|
||||||
|
// Spotlight on fog
|
||||||
|
"float ellipse;\n"
|
||||||
|
"vec2 position, size;\n"
|
||||||
|
"vec3 lSpotFogColor;\n"
|
||||||
|
|
||||||
|
// Scroll fog
|
||||||
|
"float lfogAttenuation;\n"
|
||||||
|
"vec3 lFogColor;\n"
|
||||||
|
"vec4 scrollFog;\n"
|
||||||
|
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
// Scroll fog base color
|
||||||
|
"lFogColor = fogColour.rgb * fogAmbient;\n"
|
||||||
|
|
||||||
|
// Spotlight on fog (area)
|
||||||
|
"position = spotEllipse.xy;\n"
|
||||||
|
"size = spotEllipse.zw;\n"
|
||||||
|
"ellipse = length((gl_FragCoord.xy - position) / size);\n"
|
||||||
|
"ellipse = pow(ellipse, 2.0);\n" // decay rate = square of distance from center
|
||||||
|
"ellipse = 1.0 - ellipse;\n" // invert
|
||||||
|
"ellipse = max(0.0, ellipse);\n" // clamp
|
||||||
|
|
||||||
|
// Spotlight on fog (color)
|
||||||
|
"lSpotFogColor = mix(spotFogColor * ellipse * fogColour.rgb, vec3(0.0), fogAttenuation);\n"
|
||||||
|
|
||||||
|
// Scroll fog density
|
||||||
|
"scrollFog = vec4(lFogColor + lSpotFogColor, fogColour.a);\n"
|
||||||
|
|
||||||
|
// Final Color
|
||||||
|
"gl_FragColor = scrollFog;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
|
||||||
R3DScrollFog::R3DScrollFog()
|
R3DScrollFog::R3DScrollFog()
|
||||||
{
|
{
|
||||||
//default coordinates are NDC -1,1 etc
|
//default coordinates are NDC -1,1 etc
|
||||||
|
@ -44,13 +76,13 @@ R3DScrollFog::R3DScrollFog()
|
||||||
|
|
||||||
R3DScrollFog::~R3DScrollFog()
|
R3DScrollFog::~R3DScrollFog()
|
||||||
{
|
{
|
||||||
DeallocResources();
|
DeallocResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
void R3DScrollFog::DrawScrollFog(float r, float g, float b, float a)
|
void R3DScrollFog::DrawScrollFog(float rgba[4], float attenuation, float ambient, float *spotRGB, float *spotEllipse)
|
||||||
{
|
{
|
||||||
//=======
|
//=======
|
||||||
Mat4 mvp;
|
Mat4 mvp;
|
||||||
//=======
|
//=======
|
||||||
|
|
||||||
// yeah this would have been much easier with immediate mode and fixed function .. >_<
|
// yeah this would have been much easier with immediate mode and fixed function .. >_<
|
||||||
|
@ -60,13 +92,17 @@ void R3DScrollFog::DrawScrollFog(float r, float g, float b, float a)
|
||||||
glDisable (GL_DEPTH_TEST); // disable depth testing
|
glDisable (GL_DEPTH_TEST); // disable depth testing
|
||||||
glEnable (GL_BLEND);
|
glEnable (GL_BLEND);
|
||||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
m_vbo.Bind (true);
|
m_vbo.Bind (true);
|
||||||
glUseProgram (m_shaderProgram);
|
glUseProgram (m_shaderProgram);
|
||||||
glUniform4f (m_locFogColour, r, g, b, a);
|
glUniform4f (m_locFogColour, rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||||
glUniformMatrix4fv (m_locMVP, 1, GL_FALSE, mvp);
|
glUniform1f (m_locFogAttenuation, attenuation);
|
||||||
|
glUniform1f (m_locFogAmbient, ambient);
|
||||||
glEnableClientState (GL_VERTEX_ARRAY);
|
glUniform3f (m_locSpotFogColor, spotRGB[0], spotRGB[1], spotRGB[2]);
|
||||||
|
glUniform4f (m_locSpotEllipse, spotEllipse[0], spotEllipse[1], spotEllipse[2], spotEllipse[3]);
|
||||||
|
glUniformMatrix4fv (m_locMVP, 1, GL_FALSE, mvp);
|
||||||
|
|
||||||
|
glEnableClientState (GL_VERTEX_ARRAY);
|
||||||
glVertexPointer (3, GL_FLOAT, sizeof(SFVertex), 0);
|
glVertexPointer (3, GL_FLOAT, sizeof(SFVertex), 0);
|
||||||
glDrawArrays (GL_TRIANGLES, 0, 6);
|
glDrawArrays (GL_TRIANGLES, 0, 6);
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
@ -81,12 +117,16 @@ void R3DScrollFog::DrawScrollFog(float r, float g, float b, float a)
|
||||||
void R3DScrollFog::AllocResources()
|
void R3DScrollFog::AllocResources()
|
||||||
{
|
{
|
||||||
bool success = LoadShaderProgram(&m_shaderProgram, &m_vertexShader, &m_fragmentShader, std::string(), std::string(), vertexShaderFog, fragmentShaderFog);
|
bool success = LoadShaderProgram(&m_shaderProgram, &m_vertexShader, &m_fragmentShader, std::string(), std::string(), vertexShaderFog, fragmentShaderFog);
|
||||||
|
|
||||||
m_locMVP = glGetUniformLocation(m_shaderProgram, "mvp");
|
m_locMVP = glGetUniformLocation(m_shaderProgram, "mvp");
|
||||||
m_locFogColour = glGetUniformLocation(m_shaderProgram, "fogColour");
|
m_locFogColour = glGetUniformLocation(m_shaderProgram, "fogColour");
|
||||||
|
m_locFogAttenuation = glGetUniformLocation(m_shaderProgram, "fogAttenuation");
|
||||||
m_vbo.Create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, sizeof(SFTriangle) * (2), m_triangles);
|
m_locFogAmbient = glGetUniformLocation(m_shaderProgram, "fogAmbient");
|
||||||
}
|
m_locSpotFogColor = glGetUniformLocation(m_shaderProgram, "spotFogColor");
|
||||||
|
m_locSpotEllipse = glGetUniformLocation(m_shaderProgram, "spotEllipse");
|
||||||
|
|
||||||
|
m_vbo.Create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, sizeof(SFTriangle) * (2), m_triangles);
|
||||||
|
}
|
||||||
|
|
||||||
void R3DScrollFog::DeallocResources()
|
void R3DScrollFog::DeallocResources()
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,13 +9,13 @@ class R3DScrollFog
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
R3DScrollFog();
|
R3DScrollFog();
|
||||||
~R3DScrollFog();
|
~R3DScrollFog();
|
||||||
|
|
||||||
void DrawScrollFog(float r, float g, float b, float a);
|
void DrawScrollFog(float rbga[4], float attenuation, float ambient, float *spotRGB, float *spotEllipse);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void AllocResources();
|
void AllocResources();
|
||||||
void DeallocResources();
|
void DeallocResources();
|
||||||
|
|
||||||
|
@ -42,12 +42,16 @@ private:
|
||||||
GLuint m_shaderProgram;
|
GLuint m_shaderProgram;
|
||||||
GLuint m_vertexShader;
|
GLuint m_vertexShader;
|
||||||
GLuint m_fragmentShader;
|
GLuint m_fragmentShader;
|
||||||
|
|
||||||
GLuint m_locFogColour;
|
GLuint m_locFogColour;
|
||||||
GLuint m_locMVP;
|
GLuint m_locMVP;
|
||||||
|
GLuint m_locFogAttenuation;
|
||||||
VBO m_vbo;
|
GLuint m_locFogAmbient;
|
||||||
};
|
GLuint m_locSpotFogColor;
|
||||||
|
GLuint m_locSpotEllipse;
|
||||||
|
|
||||||
|
VBO m_vbo;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,30 +2,29 @@
|
||||||
#include "Graphics/Shader.h"
|
#include "Graphics/Shader.h"
|
||||||
|
|
||||||
namespace New3D {
|
namespace New3D {
|
||||||
|
|
||||||
static const char *vertexShaderBasic =
|
static const char *vertexShaderBasic =
|
||||||
|
|
||||||
// uniforms
|
// uniforms
|
||||||
"uniform float fogIntensity;\n"
|
"uniform float fogIntensity;\n"
|
||||||
"uniform float fogDensity;\n"
|
"uniform float fogDensity;\n"
|
||||||
"uniform float fogStart;\n"
|
"uniform float fogStart;\n"
|
||||||
|
|
||||||
//outputs to fragment shader
|
//outputs to fragment shader
|
||||||
"varying float fsFogFactor;\n"
|
"varying float fsFogFactor;\n"
|
||||||
"varying float fsSpecularTerm;\n" // specular light term (additive)
|
"varying vec3 fsViewVertex;\n"
|
||||||
"varying vec3 fsViewVertex;\n"
|
"varying vec3 fsViewNormal;\n" // per vertex normal vector
|
||||||
"varying vec3 fsViewNormal;\n" // per vertex normal vector
|
|
||||||
"varying vec4 fsColor;\n"
|
"varying vec4 fsColor;\n"
|
||||||
|
|
||||||
"void main(void)\n"
|
"void main(void)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"fsViewVertex = vec3(gl_ModelViewMatrix * gl_Vertex);\n"
|
"fsViewVertex = vec3(gl_ModelViewMatrix * gl_Vertex);\n"
|
||||||
"fsViewNormal = normalize(gl_NormalMatrix *gl_Normal);\n"
|
"fsViewNormal = normalize(gl_NormalMatrix *gl_Normal);\n"
|
||||||
"float z = length(fsViewVertex);\n"
|
"float z = length(fsViewVertex);\n"
|
||||||
"fsFogFactor = fogIntensity * clamp(fogStart + z * fogDensity, 0.0, 1.0);\n"
|
"fsFogFactor = fogIntensity * clamp(fogStart + z * fogDensity, 0.0, 1.0);\n"
|
||||||
|
|
||||||
"fsColor = gl_Color;\n"
|
"fsColor = gl_Color;\n"
|
||||||
"gl_TexCoord[0] = gl_MultiTexCoord0;\n"
|
"gl_TexCoord[0] = gl_MultiTexCoord0;\n"
|
||||||
"gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
|
"gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
|
@ -41,40 +40,45 @@ static const char *fragmentShaderBasic =
|
||||||
"uniform int alphaTest;\n"
|
"uniform int alphaTest;\n"
|
||||||
"uniform int textureAlpha;\n"
|
"uniform int textureAlpha;\n"
|
||||||
"uniform vec3 fogColour;\n"
|
"uniform vec3 fogColour;\n"
|
||||||
"uniform vec4 spotEllipse;\n" // spotlight ellipse position: .x=X position (screen coordinates), .y=Y position, .z=half-width, .w=half-height)
|
"uniform vec4 spotEllipse;\n" // spotlight ellipse position: .x=X position (screen coordinates), .y=Y position, .z=half-width, .w=half-height)
|
||||||
"uniform vec2 spotRange;\n" // spotlight Z range: .x=start (viewspace coordinates), .y=limit
|
"uniform vec2 spotRange;\n" // spotlight Z range: .x=start (viewspace coordinates), .y=limit
|
||||||
"uniform vec3 spotColor;\n" // spotlight RGB color
|
"uniform vec3 spotColor;\n" // spotlight RGB color
|
||||||
"uniform vec3 lighting[2];\n" // lighting state (lighting[0] = sun direction, lighting[1].x,y = diffuse, ambient intensities from 0-1.0)
|
"uniform vec3 spotFogColor;\n" // spotlight RGB color on fog
|
||||||
"uniform int lightEnable;\n" // lighting enabled (1.0) or luminous (0.0), drawn at full intensity
|
"uniform vec3 lighting[2];\n" // lighting state (lighting[0] = sun direction, lighting[1].x,y = diffuse, ambient intensities from 0-1.0)
|
||||||
"uniform float specularCoefficient;\n" // specular coefficient
|
"uniform int lightEnable;\n" // lighting enabled (1.0) or luminous (0.0), drawn at full intensity
|
||||||
"uniform float shininess;\n" // specular shininess
|
"uniform float specularCoefficient;\n" // specular coefficient
|
||||||
|
"uniform float shininess;\n" // specular shininess
|
||||||
//interpolated inputs from vertex shader
|
"uniform float fogAttenuation;\n"
|
||||||
"varying float fsFogFactor;\n"
|
"uniform float fogAmbient;\n"
|
||||||
"varying float fsSpecularTerm;\n" // specular light term (additive)
|
|
||||||
"varying vec3 fsViewVertex;\n"
|
//interpolated inputs from vertex shader
|
||||||
"varying vec3 fsViewNormal;\n" // per vertex normal vector
|
"varying float fsFogFactor;\n"
|
||||||
|
"varying vec3 fsViewVertex;\n"
|
||||||
|
"varying vec3 fsViewNormal;\n" // per vertex normal vector
|
||||||
"varying vec4 fsColor;\n"
|
"varying vec4 fsColor;\n"
|
||||||
|
|
||||||
"void main()\n"
|
"void main()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"vec4 tex1Data;\n"
|
"vec4 tex1Data;\n"
|
||||||
"vec4 colData;\n"
|
"vec4 colData;\n"
|
||||||
"vec4 finalData;\n"
|
"vec4 finalData;\n"
|
||||||
|
"vec4 fogData;\n"
|
||||||
"bool discardFragment = false;\n"
|
|
||||||
|
"bool discardFragment = false;\n"
|
||||||
"tex1Data = vec4(1.0, 1.0, 1.0, 1.0);\n"
|
|
||||||
|
"fogData = vec4(fogColour.rgb * fogAmbient, fsFogFactor);\n"
|
||||||
"if(textureEnabled==1) {\n"
|
|
||||||
|
"tex1Data = vec4(1.0, 1.0, 1.0, 1.0);\n"
|
||||||
"tex1Data = texture2D( tex1, gl_TexCoord[0].st);\n"
|
|
||||||
|
"if(textureEnabled==1) {\n"
|
||||||
"if (microTexture==1) {\n"
|
|
||||||
"vec2 scale = baseTexSize/256.0;\n"
|
"tex1Data = texture2D( tex1, gl_TexCoord[0].st);\n"
|
||||||
"vec4 tex2Data = texture2D( tex2, gl_TexCoord[0].st * scale * microTextureScale);\n"
|
|
||||||
|
"if (microTexture==1) {\n"
|
||||||
"tex1Data = (tex1Data+tex2Data)/2.0;\n"
|
"vec2 scale = baseTexSize/256.0;\n"
|
||||||
|
"vec4 tex2Data = texture2D( tex2, gl_TexCoord[0].st * scale * microTextureScale);\n"
|
||||||
|
|
||||||
|
"tex1Data = (tex1Data+tex2Data)/2.0;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
|
||||||
"if (alphaTest==1) {\n" // does it make any sense to do this later?
|
"if (alphaTest==1) {\n" // does it make any sense to do this later?
|
||||||
|
@ -95,14 +99,20 @@ static const char *fragmentShaderBasic =
|
||||||
"discardFragment = true;\n"
|
"discardFragment = true;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
|
||||||
"if (discardFragment) {\n"
|
"if (discardFragment) {\n"
|
||||||
"discard;\n"
|
"discard;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
|
||||||
"if (lightEnable==1) {\n"
|
"float ellipse;\n"
|
||||||
"vec3 lightIntensity;\n"
|
"ellipse = length((gl_FragCoord.xy - spotEllipse.xy) / spotEllipse.zw);\n"
|
||||||
"vec3 sunVector;\n" // sun lighting vector (as reflecting away from vertex)
|
"ellipse = pow(ellipse, 2.0);\n" // decay rate = square of distance from center
|
||||||
"float sunFactor;\n" // sun light projection along vertex normal (0.0 to 1.0)
|
"ellipse = 1.0 - ellipse;\n" // invert
|
||||||
|
"ellipse = max(0.0, ellipse);\n" // clamp
|
||||||
|
|
||||||
|
"if (lightEnable==1) {\n"
|
||||||
|
"vec3 lightIntensity;\n"
|
||||||
|
"vec3 sunVector;\n" // sun lighting vector (as reflecting away from vertex)
|
||||||
|
"float sunFactor;\n" // sun light projection along vertex normal (0.0 to 1.0)
|
||||||
|
|
||||||
// Real3D -> OpenGL view space convention (TO-DO: do this outside of shader)
|
// Real3D -> OpenGL view space convention (TO-DO: do this outside of shader)
|
||||||
"sunVector = lighting[0] * vec3(1.0, -1.0, -1.0);\n"
|
"sunVector = lighting[0] * vec3(1.0, -1.0, -1.0);\n"
|
||||||
|
@ -112,40 +122,43 @@ static const char *fragmentShaderBasic =
|
||||||
|
|
||||||
// Total light intensity: sum of all components
|
// Total light intensity: sum of all components
|
||||||
"lightIntensity = vec3(sunFactor*lighting[1].x + lighting[1].y);\n" // ambient + diffuse
|
"lightIntensity = vec3(sunFactor*lighting[1].x + lighting[1].y);\n" // ambient + diffuse
|
||||||
|
|
||||||
"lightIntensity = clamp(lightIntensity,0.0,1.0);\n"
|
"lightIntensity = clamp(lightIntensity,0.0,1.0);\n"
|
||||||
|
|
||||||
"vec2 ellipse;\n"
|
// Compute spotlight and apply lighting
|
||||||
"float insideSpot;\n"
|
"float enable, range, d;\n"
|
||||||
|
"float inv_r = 1.0 / spotEllipse.z;\n" // slope of decay function
|
||||||
// Compute spotlight and apply lighting
|
|
||||||
"ellipse = (gl_FragCoord.xy - spotEllipse.xy) / spotEllipse.zw;\n"
|
"d = spotRange.x + spotRange.y + fsViewVertex.z;\n"
|
||||||
"insideSpot = dot(ellipse, ellipse);\n"
|
"enable = step(spotRange.x + min(spotRange.y, 0.0), -fsViewVertex.z);\n"
|
||||||
|
|
||||||
"if ((insideSpot <= 1.0) && (-fsViewVertex.z >= spotRange.x)) {\n"
|
// inverse-linear falloff
|
||||||
"lightIntensity.rgb += (1.0 - insideSpot)*spotColor;\n"
|
// Reference: https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/
|
||||||
"}\n"
|
// y = 1 / (d/r + 1)^2
|
||||||
|
"range = 1.0 / pow(min(0.0, d * inv_r) - 1.0, 2.0);\n"
|
||||||
"finalData.rgb *= lightIntensity;\n"
|
"range = clamp(range, 0.0, 1.0);\n"
|
||||||
|
"range *= enable;\n"
|
||||||
"if (sunFactor > 0.0 && specularCoefficient > 0.0) {\n"
|
|
||||||
|
"float lobeEffect = range * ellipse;\n"
|
||||||
"float nDotL = max(dot(fsViewNormal,sunVector),0.0);\n"
|
|
||||||
|
"lightIntensity.rgb += spotColor*lobeEffect;\n"
|
||||||
"finalData.rgb += vec3(specularCoefficient * pow(nDotL,shininess));\n"
|
|
||||||
|
"finalData.rgb *= lightIntensity;\n"
|
||||||
//"vec3 v = normalize(-fsViewVertex);\n"
|
|
||||||
//"vec3 h = normalize(sunVector + v);\n" // halfway vector
|
"if (sunFactor > 0.0 && specularCoefficient > 0.0) {\n"
|
||||||
//"float NdotHV = max(dot(fsViewNormal,h),0.0);\n"
|
"float nDotL = max(dot(fsViewNormal,sunVector),0.0);\n"
|
||||||
//"finalData.rgb += vec3(specularCoefficient * pow(NdotHV,shininess));\n"
|
"finalData.rgb += vec3(specularCoefficient * pow(nDotL,shininess));\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
|
||||||
|
// Spotlight on fog
|
||||||
"finalData.rgb = mix(finalData.rgb, fogColour, fsFogFactor);\n"
|
"vec3 lSpotFogColor = spotFogColor * ellipse * fogColour.rgb;\n"
|
||||||
|
|
||||||
"gl_FragColor = finalData;\n"
|
// Fog & spotlight applied
|
||||||
"}\n";
|
"finalData.rgb = mix(finalData.rgb, lSpotFogColor * fogAttenuation + fogData.rgb, fogData.a);\n"
|
||||||
|
|
||||||
|
"gl_FragColor = finalData;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
R3DShader::R3DShader()
|
R3DShader::R3DShader()
|
||||||
{
|
{
|
||||||
|
@ -211,20 +224,23 @@ bool R3DShader::LoadShader(const char* vertexShader, const char* fragmentShader)
|
||||||
m_locBaseTexSize = glGetUniformLocation(m_shaderProgram, "baseTexSize");
|
m_locBaseTexSize = glGetUniformLocation(m_shaderProgram, "baseTexSize");
|
||||||
|
|
||||||
m_locFogIntensity = glGetUniformLocation(m_shaderProgram, "fogIntensity");
|
m_locFogIntensity = glGetUniformLocation(m_shaderProgram, "fogIntensity");
|
||||||
m_locFogDensity = glGetUniformLocation(m_shaderProgram, "fogDensity");
|
m_locFogDensity = glGetUniformLocation(m_shaderProgram, "fogDensity");
|
||||||
m_locFogStart = glGetUniformLocation(m_shaderProgram, "fogStart");
|
m_locFogStart = glGetUniformLocation(m_shaderProgram, "fogStart");
|
||||||
m_locFogColour = glGetUniformLocation(m_shaderProgram, "fogColour");
|
m_locFogColour = glGetUniformLocation(m_shaderProgram, "fogColour");
|
||||||
|
m_locFogAttenuation = glGetUniformLocation(m_shaderProgram, "fogAttenuation");
|
||||||
m_locLighting = glGetUniformLocation(m_shaderProgram, "lighting");
|
m_locFogAmbient = glGetUniformLocation(m_shaderProgram, "fogAmbient");
|
||||||
m_locLightEnable = glGetUniformLocation(m_shaderProgram, "lightEnable");
|
|
||||||
|
m_locLighting = glGetUniformLocation(m_shaderProgram, "lighting");
|
||||||
|
m_locLightEnable = glGetUniformLocation(m_shaderProgram, "lightEnable");
|
||||||
m_locShininess = glGetUniformLocation(m_shaderProgram, "shininess");
|
m_locShininess = glGetUniformLocation(m_shaderProgram, "shininess");
|
||||||
m_locSpecCoefficient= glGetUniformLocation(m_shaderProgram, "specularCoefficient");
|
m_locSpecCoefficient= glGetUniformLocation(m_shaderProgram, "specularCoefficient");
|
||||||
m_locSpotEllipse = glGetUniformLocation(m_shaderProgram, "spotEllipse");
|
m_locSpotEllipse = glGetUniformLocation(m_shaderProgram, "spotEllipse");
|
||||||
m_locSpotRange = glGetUniformLocation(m_shaderProgram, "spotRange");
|
m_locSpotRange = glGetUniformLocation(m_shaderProgram, "spotRange");
|
||||||
m_locSpotColor = glGetUniformLocation(m_shaderProgram, "spotColor");
|
m_locSpotColor = glGetUniformLocation(m_shaderProgram, "spotColor");
|
||||||
|
m_locSpotFogColor = glGetUniformLocation(m_shaderProgram, "spotFogColor");
|
||||||
return success;
|
|
||||||
}
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
void R3DShader::SetShader(bool enable)
|
void R3DShader::SetShader(bool enable)
|
||||||
{
|
{
|
||||||
|
@ -331,17 +347,20 @@ void R3DShader::SetMeshUniforms(const Mesh* m)
|
||||||
void R3DShader::SetViewportUniforms(const Viewport *vp)
|
void R3DShader::SetViewportUniforms(const Viewport *vp)
|
||||||
{
|
{
|
||||||
//didn't bother caching these, they don't get frequently called anyway
|
//didn't bother caching these, they don't get frequently called anyway
|
||||||
glUniform1f (m_locFogDensity, vp->fogParams[3]);
|
glUniform1f (m_locFogDensity, vp->fogParams[3]);
|
||||||
glUniform1f (m_locFogStart, vp->fogParams[4]);
|
glUniform1f (m_locFogStart, vp->fogParams[4]);
|
||||||
glUniform3fv(m_locFogColour, 1, vp->fogParams);
|
glUniform3fv(m_locFogColour, 1, vp->fogParams);
|
||||||
|
glUniform1f (m_locFogAttenuation, vp->fogParams[5]);
|
||||||
glUniform3fv(m_locLighting, 2, vp->lightingParams);
|
glUniform1f (m_locFogAmbient, vp->fogParams[6]);
|
||||||
glUniform4fv(m_locSpotEllipse, 1, vp->spotEllipse);
|
|
||||||
glUniform2fv(m_locSpotRange, 1, vp->spotRange);
|
glUniform3fv(m_locLighting, 2, vp->lightingParams);
|
||||||
glUniform3fv(m_locSpotColor, 1, vp->spotColor);
|
glUniform4fv(m_locSpotEllipse, 1, vp->spotEllipse);
|
||||||
}
|
glUniform2fv(m_locSpotRange, 1, vp->spotRange);
|
||||||
|
glUniform3fv(m_locSpotColor, 1, vp->spotColor);
|
||||||
void R3DShader::SetModelStates(const Model* model)
|
glUniform3fv(m_locSpotFogColor, 1, vp->spotFogColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void R3DShader::SetModelStates(const Model* model)
|
||||||
{
|
{
|
||||||
//==========
|
//==========
|
||||||
MatDet test;
|
MatDet test;
|
||||||
|
|
|
@ -59,20 +59,23 @@ private:
|
||||||
|
|
||||||
// viewport uniform locations
|
// viewport uniform locations
|
||||||
GLint m_locFogIntensity;
|
GLint m_locFogIntensity;
|
||||||
GLint m_locFogDensity;
|
GLint m_locFogDensity;
|
||||||
GLint m_locFogStart;
|
GLint m_locFogStart;
|
||||||
GLint m_locFogColour;
|
GLint m_locFogColour;
|
||||||
|
GLint m_locFogAttenuation;
|
||||||
// lighting
|
GLint m_locFogAmbient;
|
||||||
GLint m_locLighting;
|
|
||||||
|
// lighting
|
||||||
|
GLint m_locLighting;
|
||||||
GLint m_locLightEnable;
|
GLint m_locLightEnable;
|
||||||
GLint m_locShininess;
|
GLint m_locShininess;
|
||||||
GLint m_locSpecCoefficient;
|
GLint m_locSpecCoefficient;
|
||||||
GLint m_locSpotEllipse;
|
GLint m_locSpotEllipse;
|
||||||
GLint m_locSpotRange;
|
GLint m_locSpotRange;
|
||||||
GLint m_locSpotColor;
|
GLint m_locSpotColor;
|
||||||
};
|
GLint m_locSpotFogColor;
|
||||||
|
};
|
||||||
} // New3D
|
|
||||||
|
} // New3D
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in a new issue