Texture-based fog table
This commit is contained in:
parent
96157de639
commit
ffb72cd0b6
|
@ -22,6 +22,9 @@ int fbdev = -1;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef GL_RED
|
||||
#define GL_RED 0x1903
|
||||
#endif
|
||||
#ifndef GL_MAJOR_VERSION
|
||||
#define GL_MAJOR_VERSION 0x821B
|
||||
#endif
|
||||
|
@ -89,7 +92,6 @@ const char* VertexShaderSource =
|
|||
/* Vertex constants*/ \n\
|
||||
uniform highp vec4 scale; \n\
|
||||
uniform highp vec4 depth_scale; \n\
|
||||
uniform highp float sp_FOG_DENSITY; \n\
|
||||
/* Vertex input */ \n\
|
||||
in highp vec4 in_pos; \n\
|
||||
in lowp vec4 in_base; \n\
|
||||
|
@ -99,15 +101,12 @@ in mediump vec2 in_uv; \n\
|
|||
out lowp vec4 vtx_base; \n\
|
||||
out lowp vec4 vtx_offs; \n\
|
||||
out mediump vec2 vtx_uv; \n\
|
||||
out highp vec3 vtx_xyz; \n\
|
||||
void main() \n\
|
||||
{ \n\
|
||||
vtx_base=in_base; \n\
|
||||
vtx_offs=in_offs; \n\
|
||||
vtx_uv=in_uv; \n\
|
||||
vec4 vpos=in_pos; \n\
|
||||
vtx_xyz.xy = vpos.xy; \n\
|
||||
vtx_xyz.z = vpos.z*sp_FOG_DENSITY; \n\
|
||||
vpos.w=1.0/vpos.z; \n\
|
||||
#if TARGET_GL != GLES2 \n\
|
||||
if (vpos.w < 0.0) { \n\
|
||||
|
@ -254,12 +253,15 @@ const char* PixelPipelineShader =
|
|||
#if TARGET_GL == GLES3 \n\
|
||||
out highp vec4 FragColor; \n\
|
||||
#define gl_FragColor FragColor \n\
|
||||
#define FOG_CHANNEL a \n\
|
||||
#elif TARGET_GL == GL3 \n\
|
||||
out highp vec4 FragColor; \n\
|
||||
#define gl_FragColor FragColor \n\
|
||||
#define FOG_CHANNEL r \n\
|
||||
#else \n\
|
||||
#define in varying \n\
|
||||
#define texture texture2D \n\
|
||||
#define FOG_CHANNEL a \n\
|
||||
#endif \n\
|
||||
\n\
|
||||
/* Shader program params*/ \n\
|
||||
|
@ -267,17 +269,20 @@ out highp vec4 FragColor; \n\
|
|||
uniform lowp float cp_AlphaTestValue; \n\
|
||||
uniform lowp vec4 pp_ClipTest; \n\
|
||||
uniform lowp vec3 sp_FOG_COL_RAM,sp_FOG_COL_VERT; \n\
|
||||
uniform highp vec2 sp_LOG_FOG_COEFS; \n\
|
||||
uniform highp float sp_FOG_DENSITY; \n\
|
||||
uniform sampler2D tex,fog_table; \n\
|
||||
/* Vertex input*/ \n\
|
||||
in lowp vec4 vtx_base; \n\
|
||||
in lowp vec4 vtx_offs; \n\
|
||||
in mediump vec2 vtx_uv; \n\
|
||||
in highp vec3 vtx_xyz; \n\
|
||||
lowp float fog_mode2(highp float val) \n\
|
||||
lowp float fog_mode2(highp float w) \n\
|
||||
{ \n\
|
||||
highp float fog_idx=clamp(val,0.0,127.99); \n\
|
||||
return clamp(sp_LOG_FOG_COEFS.y*log2(fog_idx)+sp_LOG_FOG_COEFS.x,0.001,1.0); //the clamp is required due to yet another bug !\n\
|
||||
highp float z = clamp(w * sp_FOG_DENSITY, 1.0, 255.9999); \n\
|
||||
highp float exp = floor(log2(z)); \n\
|
||||
highp float m = z * 16.0 / pow(2.0, exp) - 16.0; \n\
|
||||
lowp float idx = floor(m) + exp * 16.0 + 0.5; \n\
|
||||
highp vec4 fog_coef = texture(fog_table, vec2(idx / 128.0, 0.75 - (m - floor(m)) / 2.0)); \n\
|
||||
return fog_coef.FOG_CHANNEL; \n\
|
||||
} \n\
|
||||
void main() \n\
|
||||
{ \n\
|
||||
|
@ -299,7 +304,7 @@ void main() \n\
|
|||
color.a=1.0; \n\
|
||||
#endif\n\
|
||||
#if pp_FogCtrl==3 \n\
|
||||
color=vec4(sp_FOG_COL_RAM.rgb,fog_mode2(vtx_xyz.z)); \n\
|
||||
color=vec4(sp_FOG_COL_RAM.rgb,fog_mode2(gl_FragCoord.w)); \n\
|
||||
#endif\n\
|
||||
#if pp_Texture==1 \n\
|
||||
{ \n\
|
||||
|
@ -343,7 +348,7 @@ void main() \n\
|
|||
#endif\n\
|
||||
#if pp_FogCtrl==0 \n\
|
||||
{ \n\
|
||||
color.rgb=mix(color.rgb,sp_FOG_COL_RAM.rgb,fog_mode2(vtx_xyz.z)); \n\
|
||||
color.rgb=mix(color.rgb,sp_FOG_COL_RAM.rgb,fog_mode2(gl_FragCoord.w)); \n\
|
||||
} \n\
|
||||
#endif\n\
|
||||
#if cp_AlphaTest == 1 \n\
|
||||
|
@ -353,7 +358,6 @@ void main() \n\
|
|||
else \n\
|
||||
color.a = 1.0; \n\
|
||||
#endif \n\
|
||||
//color.rgb=vec3(vtx_xyz.z/255.0);\n\
|
||||
#if TARGET_GL != GLES2 \n\
|
||||
highp float w = gl_FragCoord.w * 100000.0; \n\
|
||||
gl_FragDepth = log2(1.0 + w) / 34.0; \n\
|
||||
|
@ -422,6 +426,7 @@ gl_ctx gl;
|
|||
|
||||
int screen_width;
|
||||
int screen_height;
|
||||
GLuint fogTextureId;
|
||||
|
||||
#if (HOST_OS != OS_DARWIN) && !defined(TARGET_NACL32)
|
||||
#if defined(GLES) && !defined(USE_SDL)
|
||||
|
@ -749,6 +754,7 @@ void findGLVersion()
|
|||
gl.gl_version = "GLES2";
|
||||
gl.glsl_version_header = "";
|
||||
}
|
||||
gl.fog_image_format = GL_ALPHA;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -757,11 +763,13 @@ void findGLVersion()
|
|||
{
|
||||
gl.gl_version = "GL3";
|
||||
gl.glsl_version_header = "#version 130";
|
||||
gl.fog_image_format = GL_RED;
|
||||
}
|
||||
else
|
||||
{
|
||||
gl.gl_version = "GL2";
|
||||
gl.glsl_version_header = "#version 120";
|
||||
gl.fog_image_format = GL_ALPHA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -774,7 +782,6 @@ struct ShaderUniforms_t
|
|||
float fog_den_float;
|
||||
float ps_FOG_COL_RAM[3];
|
||||
float ps_FOG_COL_VERT[3];
|
||||
float fog_coefs[2];
|
||||
|
||||
void Set(PipelineShader* s)
|
||||
{
|
||||
|
@ -795,9 +802,6 @@ struct ShaderUniforms_t
|
|||
|
||||
if (s->sp_FOG_COL_VERT!=-1)
|
||||
glUniform3fv( s->sp_FOG_COL_VERT, 1, ps_FOG_COL_VERT);
|
||||
|
||||
if (s->sp_LOG_FOG_COEFS!=-1)
|
||||
glUniform2fv(s->sp_LOG_FOG_COEFS,1, fog_coefs);
|
||||
}
|
||||
|
||||
} ShaderUniforms;
|
||||
|
@ -936,14 +940,15 @@ bool CompilePipelineShader( PipelineShader* s)
|
|||
if (s->pp_FogCtrl==0 || s->pp_FogCtrl==3)
|
||||
{
|
||||
s->sp_FOG_COL_RAM=glGetUniformLocation(s->program, "sp_FOG_COL_RAM");
|
||||
s->sp_LOG_FOG_COEFS=glGetUniformLocation(s->program, "sp_LOG_FOG_COEFS");
|
||||
}
|
||||
else
|
||||
{
|
||||
s->sp_FOG_COL_RAM=-1;
|
||||
s->sp_LOG_FOG_COEFS=-1;
|
||||
}
|
||||
|
||||
// Setup texture 1 as the fog table
|
||||
gu = glGetUniformLocation(s->program, "fog_table");
|
||||
if (gu != -1)
|
||||
glUniform1i(gu, 1);
|
||||
|
||||
ShaderUniforms.Set(s);
|
||||
|
||||
|
@ -1095,70 +1100,35 @@ bool gles_init()
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
float fog_coefs[]={0,0};
|
||||
void tryfit(float* x,float* y)
|
||||
void UpdateFogTexture(u8 *fog_table, GLenum texture_slot, GLint fog_image_format)
|
||||
{
|
||||
//y=B*ln(x)+A
|
||||
|
||||
double sylnx=0,sy=0,slnx=0,slnx2=0;
|
||||
|
||||
u32 cnt=0;
|
||||
|
||||
for (int i=0;i<128;i++)
|
||||
glActiveTexture(texture_slot);
|
||||
if (fogTextureId == 0)
|
||||
{
|
||||
int rep=1;
|
||||
|
||||
//discard values clipped to 0 or 1
|
||||
if (y[i]==1 && y[i+1]==1)
|
||||
continue;
|
||||
|
||||
if (i>0 && y[i]==0 && y[i-1]==0)
|
||||
continue;
|
||||
|
||||
//Add many samples for first and last value (fog-in, fog-out -> important)
|
||||
if (i>0 && y[i]!=1 && y[i-1]==1)
|
||||
rep=10000;
|
||||
|
||||
if (y[i]!=0 && y[i+1]==0)
|
||||
rep=10000;
|
||||
|
||||
for (int j=0;j<rep;j++)
|
||||
{
|
||||
cnt++;
|
||||
sylnx+=y[i]*log((double)x[i]);
|
||||
sy+=y[i];
|
||||
slnx+=log((double)x[i]);
|
||||
slnx2+=log((double)x[i])*log((double)x[i]);
|
||||
}
|
||||
glGenTextures(1, &fogTextureId);
|
||||
glBindTexture(GL_TEXTURE_2D, fogTextureId);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
else
|
||||
glBindTexture(GL_TEXTURE_2D, fogTextureId);
|
||||
|
||||
double a,b;
|
||||
b=(cnt*sylnx-sy*slnx)/(cnt*slnx2-slnx*slnx);
|
||||
a=(sy-b*slnx)/(cnt);
|
||||
|
||||
|
||||
//We use log2 and not ln on calculations //B*log(x)+A
|
||||
//log2(x)=log(x)/log(2)
|
||||
//log(x)=log2(x)*log(2)
|
||||
//B*log(2)*log(x)+A
|
||||
b*=logf(2.0);
|
||||
|
||||
float maxdev=0;
|
||||
for (int i=0;i<128;i++)
|
||||
u8 temp_tex_buffer[256];
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
float diff=min(max(b*logf(x[i])/logf(2.0)+a,(double)0),(double)1)-y[i];
|
||||
maxdev=max((float)fabs((float)diff),(float)maxdev);
|
||||
temp_tex_buffer[i] = fog_table[i * 4];
|
||||
temp_tex_buffer[i + 128] = fog_table[i * 4 + 1];
|
||||
}
|
||||
printf("FOG TABLE Curve match: maxdev: %.02f cents\n",maxdev*100);
|
||||
fog_coefs[0]=a;
|
||||
fog_coefs[1]=b;
|
||||
//printf("%f\n",B*log(maxdev)/log(2.0)+A);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, fog_image_format, 128, 2, 0, fog_image_format, GL_UNSIGNED_BYTE, temp_tex_buffer);
|
||||
glCheck();
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern u16 kcode[4];
|
||||
extern u8 rt[4],lt[4];
|
||||
|
||||
|
@ -1700,8 +1670,6 @@ bool RenderFrame()
|
|||
dc_width *= scale_x;
|
||||
dc_height *= scale_y;
|
||||
|
||||
glUseProgram(gl.modvol_shader.program);
|
||||
|
||||
/*
|
||||
|
||||
float vnear=0;
|
||||
|
@ -1764,21 +1732,10 @@ bool RenderFrame()
|
|||
s32 fog_den_exp=(s8)fog_density[0];
|
||||
ShaderUniforms.fog_den_float=fog_den_mant*powf(2.0f,fog_den_exp);
|
||||
|
||||
|
||||
if (fog_needs_update)
|
||||
{
|
||||
fog_needs_update=false;
|
||||
//Get the coefs for the fog curve
|
||||
u8* fog_table=(u8*)FOG_TABLE;
|
||||
float xvals[128];
|
||||
float yvals[128];
|
||||
for (int i=0;i<128;i++)
|
||||
{
|
||||
xvals[i]=powf(2.0f,i>>4)*(1+(i&15)/16.f);
|
||||
yvals[i]=fog_table[i*4+1]/255.0f;
|
||||
}
|
||||
|
||||
tryfit(xvals,yvals);
|
||||
fog_needs_update = false;
|
||||
UpdateFogTexture((u8 *)FOG_TABLE, GL_TEXTURE1, gl.fog_image_format);
|
||||
}
|
||||
|
||||
glUseProgram(gl.modvol_shader.program);
|
||||
|
|
|
@ -53,7 +53,7 @@ struct PipelineShader
|
|||
|
||||
GLuint scale,depth_scale;
|
||||
GLuint pp_ClipTest,cp_AlphaTestValue;
|
||||
GLuint sp_FOG_COL_RAM,sp_FOG_COL_VERT,sp_FOG_DENSITY,sp_LOG_FOG_COEFS;
|
||||
GLuint sp_FOG_COL_RAM,sp_FOG_COL_VERT,sp_FOG_DENSITY;
|
||||
|
||||
//
|
||||
u32 cp_AlphaTest; s32 pp_ClipTestMode;
|
||||
|
@ -101,7 +101,7 @@ struct gl_ctx
|
|||
const char *glsl_version_header;
|
||||
int gl_major;
|
||||
bool is_gles;
|
||||
|
||||
GLuint fog_image_format;
|
||||
//GLuint matrix;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue