- implement alpha test

This commit is contained in:
Magnus Norddahl 2019-08-16 04:10:03 +02:00
parent 8ea439a5c2
commit c4dafbedc1
11 changed files with 127 additions and 66 deletions

View file

@ -16,7 +16,6 @@ RenderDevice::RenderDevice(HWND hwnd) : Context(hwnd)
{
Context.Begin();
mShaderManager = std::make_unique<ShaderManager>();
mShader = &mShaderManager->Shaders[(int)ShaderName::basic];
Context.End();
}
}
@ -344,6 +343,14 @@ void RenderDevice::CheckError()
throw std::runtime_error("OpenGL error!");
}
Shader* RenderDevice::GetActiveShader()
{
if (mAlphaTest)
return &mShaderManager->AlphaTestShaders[(int)mShaderName];
else
return &mShaderManager->Shaders[(int)mShaderName];
}
void RenderDevice::ApplyChanges()
{
ApplyShader();
@ -363,7 +370,7 @@ void RenderDevice::ApplyChanges()
void RenderDevice::ApplyShader()
{
glUseProgram(mShader->GetProgram());
glUseProgram(GetActiveShader()->GetProgram());
}
void RenderDevice::ApplyRasterizerState()
@ -472,16 +479,17 @@ void RenderDevice::ApplyVertexBuffers()
void RenderDevice::ApplyMatrices()
{
Shader* shader = GetActiveShader();
for (size_t i = 0; i < (size_t)TransformState::NumTransforms; i++)
{
auto& binding = mTransforms[i];
glUniformMatrix4fv(mShader->TransformLocations[i], 1, GL_FALSE, binding.Values);
glUniformMatrix4fv(shader->TransformLocations[i], 1, GL_FALSE, binding.Values);
}
}
void RenderDevice::SetShader(ShaderName name)
{
mShader = &mShaderManager->Shaders[(int)name];
mShaderName = name;
mNeedApply = true;
}
@ -513,7 +521,8 @@ void RenderDevice::SetUniform(UniformName name, const void* values, int count)
void RenderDevice::ApplyUniforms()
{
auto& locations = mShader->UniformLocations;
Shader* shader = GetActiveShader();
auto& locations = shader->UniformLocations;
glUniformMatrix4fv(locations[(int)UniformName::transformsettings], 1, GL_FALSE, &mUniforms[0].valuef);
glUniformMatrix4fv(locations[(int)UniformName::worldviewproj], 1, GL_FALSE, &mUniforms[16].valuef);
@ -535,6 +544,9 @@ void RenderDevice::ApplyUniforms()
glUniform1fv(locations[(int)UniformName::desaturation], 1, &mUniforms[108].valuef);
glUniform1fv(locations[(int)UniformName::ignoreNormals], 1, &mUniforms[109].valuef);
glUniform1fv(locations[(int)UniformName::spotLight], 1, &mUniforms[110].valuef);
for (int i = 0; i < Shader::MaxSamplers; i++)
glUniform1i(shader->SamplerLocations[i], i);
}
void RenderDevice::ApplyTextures()

View file

@ -135,6 +135,8 @@ public:
void CheckError();
Shader* GetActiveShader();
GLint GetGLMinFilter(TextureFilter filter, TextureFilter mipfilter);
OpenGLContext Context;
@ -172,7 +174,7 @@ public:
IndexBuffer* mIndexBuffer = nullptr;
std::unique_ptr<ShaderManager> mShaderManager;
Shader* mShader = nullptr;
ShaderName mShaderName = ShaderName::basic;
struct Mat4f
{

View file

@ -18,13 +18,25 @@ void Shader::ReleaseResources()
mFragmentShader = 0;
}
bool Shader::Compile(const std::string& vertexShader, const std::string& fragmentShader)
bool Shader::Compile(const std::string& vertexShader, const std::string& fragmentShader, bool alphatest)
{
mVertexShader = CompileShader(vertexShader, GL_VERTEX_SHADER);
const char* prefixNAT = R"(
#version 150
#line 1
)";
const char* prefixAT = R"(
#version 150
#define ALPHA_TEST
#line 1
)";
const char* prefix = alphatest ? prefixAT : prefixNAT;
mVertexShader = CompileShader(prefix + vertexShader, GL_VERTEX_SHADER);
if (!mVertexShader)
return false;
mFragmentShader = CompileShader(fragmentShader, GL_FRAGMENT_SHADER);
mFragmentShader = CompileShader(prefix + fragmentShader, GL_FRAGMENT_SHADER);
if (!mFragmentShader)
return false;
@ -85,6 +97,11 @@ bool Shader::Compile(const std::string& vertexShader, const std::string& fragmen
UniformLocations[i] = glGetUniformLocation(mProgram, names[i]);
}
for (int i = 0; i < MaxSamplers; i++)
{
SamplerLocations[i] = glGetUniformLocation(mProgram, ("texture" + std::to_string(i + 1)).c_str());
}
return mProgram;
}

View file

@ -9,7 +9,7 @@ public:
Shader() = default;
void ReleaseResources();
bool Compile(const std::string& vertexShader, const std::string& fragmentShader);
bool Compile(const std::string& vertexShader, const std::string& fragmentShader, bool alphatest);
const char* GetErrors() const { return mErrors.c_str(); }
GLuint GetProgram() const { return mProgram; }
@ -17,6 +17,9 @@ public:
GLuint TransformLocations[(int)TransformState::NumTransforms] = { 0 };
GLuint UniformLocations[(int)UniformName::NumUniforms] = { 0 };
enum { MaxSamplers = 4 };
GLuint SamplerLocations[MaxSamplers] = { };
private:
GLuint CompileShader(const std::string& code, GLenum type);

View file

@ -1,8 +1,6 @@
#pragma once
static const char* default_vs = R"(
#version 150
in vec4 AttrPosition;
in vec4 AttrColor;
in vec2 AttrUV;
@ -26,8 +24,6 @@ static const char* default_vs = R"(
)";
static const char* default_ps = R"(
#version 150
in vec4 Color;
in vec2 UV;
in vec3 Normal;
@ -37,5 +33,9 @@ static const char* default_ps = R"(
void main()
{
FragColor = vec4(UV, 1.0, 1.0);
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";

View file

@ -1,8 +1,6 @@
#pragma once
static const char* display2D_vs = R"(
#version 150
in vec3 AttrPosition;
in vec4 AttrColor;
in vec2 AttrUV;
@ -21,8 +19,6 @@ static const char* display2D_vs = R"(
)";
static const char* display2D_ps_fsaa = R"(
#version 150
in vec4 Color;
in vec2 UV;
@ -74,12 +70,14 @@ static const char* display2D_ps_fsaa = R"(
{
FragColor = vec4(desaturate(c.rgb), c.a * rendersettings.w) * Color;
}
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";
const char* display2D_ps_normal = R"(
#version 150
in vec4 Color;
in vec2 UV;
@ -105,12 +103,14 @@ const char* display2D_ps_normal = R"(
{
vec4 c = texture(texture1, UV);
FragColor = vec4(desaturate(c.rgb), c.a * rendersettings.w) * Color;
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";
const char* display2D_ps_fullbright = R"(
#version 150
in vec4 Color;
in vec2 UV;
@ -129,5 +129,9 @@ const char* display2D_ps_fullbright = R"(
{
vec4 c = texture(texture1, UV);
FragColor = vec4(c.rgb, c.a * rendersettings.w);
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";

View file

@ -43,7 +43,13 @@ ShaderManager::ShaderManager()
{
if (ShaderSources[i].vs && ShaderSources[i].ps)
{
if (!Shaders[i].Compile(ShaderSources[i].vs, ShaderSources[i].ps))
if (!Shaders[i].Compile(ShaderSources[i].vs, ShaderSources[i].ps, false))
{
CompileErrors += "Could not compile " + std::to_string(i) + "\r\n";
CompileErrors += Shaders[i].GetErrors();
}
if (!AlphaTestShaders[i].Compile(ShaderSources[i].vs, ShaderSources[i].ps, true))
{
CompileErrors += "Could not compile " + std::to_string(i) + "\r\n";
CompileErrors += Shaders[i].GetErrors();

View file

@ -8,6 +8,7 @@ public:
ShaderManager();
void ReleaseResources();
Shader AlphaTestShaders[(int)ShaderName::count];
Shader Shaders[(int)ShaderName::count];
std::string CompileErrors;

View file

@ -1,8 +1,6 @@
#pragma once
static const char* things2D_vs = R"(
#version 150
in vec3 AttrPosition;
in vec4 AttrColor;
in vec2 AttrUV;
@ -21,8 +19,6 @@ static const char* things2D_vs = R"(
)";
static const char* things2D_ps_sprite = R"(
#version 150
in vec4 Color;
in vec2 UV;
@ -57,12 +53,14 @@ static const char* things2D_ps_sprite = R"(
// Or leave it as it is
FragColor = vec4(desaturate(c.rgb), c.a * rendersettings.w);
}
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";
static const char* things2D_ps_thing = R"(
#version 150
in vec4 Color;
in vec2 UV;
@ -85,12 +83,14 @@ static const char* things2D_ps_thing = R"(
{
vec4 c = texture(texture1, UV);
FragColor = vec4(desaturate(c.rgb), c.a * rendersettings.w) * Color;
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";
static const char* things2D_ps_fill = R"(
#version 150
in vec4 Color;
in vec2 UV;
@ -101,5 +101,9 @@ static const char* things2D_ps_fill = R"(
void main()
{
FragColor = fillColor;
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";

View file

@ -1,8 +1,6 @@
#pragma once
static const char* world3D_vs_main = R"(
#version 150
in vec3 AttrPosition;
in vec4 AttrColor;
in vec2 AttrUV;
@ -22,8 +20,6 @@ static const char* world3D_vs_main = R"(
)";
static const char* world3D_vs_customvertexcolor = R"(
#version 150
in vec3 AttrPosition;
in vec4 AttrColor;
in vec2 AttrUV;
@ -44,8 +40,6 @@ static const char* world3D_vs_customvertexcolor = R"(
)";
static const char* world3D_vs_customvertexcolor_fog = R"(
#version 150
in vec3 AttrPosition;
in vec4 AttrColor;
in vec2 AttrUV;
@ -72,8 +66,6 @@ static const char* world3D_vs_customvertexcolor_fog = R"(
)";
static const char* world3D_vs_lightpass = R"(
#version 150
in vec3 AttrPosition;
in vec4 AttrColor;
in vec2 AttrUV;
@ -99,8 +91,6 @@ static const char* world3D_vs_lightpass = R"(
)";
static const char* world3D_vs_skybox = R"(
#version 150
in vec3 AttrPosition;
in vec2 AttrUV;
@ -121,8 +111,6 @@ static const char* world3D_vs_skybox = R"(
)";
static const char* world3D_ps_main = R"(
#version 150
in vec4 Color;
in vec2 UV;
@ -144,12 +132,14 @@ static const char* world3D_ps_main = R"(
vec4 tcolor = texture(texture1, UV);
tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a);
FragColor = desaturate(tcolor * Color);
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";
static const char* world3D_ps_fullbright = R"(
#version 150
in vec4 Color;
in vec2 UV;
@ -165,12 +155,14 @@ static const char* world3D_ps_fullbright = R"(
tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a);
tcolor.a *= Color.a;
FragColor = tcolor;
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";
static const char* world3D_ps_main_highlight = R"(
#version 150
in vec4 Color;
in vec2 UV;
@ -203,12 +195,14 @@ static const char* world3D_ps_main_highlight = R"(
FragColor = vec4(highlightcolor.rgb * highlightcolor.a + (ncolor.rgb - 0.4 * highlightcolor.a), max(Color.a + 0.25, 0.5));
}
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";
static const char* world3D_ps_fullbright_highlight = R"(
#version 150
in vec4 Color;
in vec2 UV;
@ -234,12 +228,14 @@ static const char* world3D_ps_fullbright_highlight = R"(
FragColor = vec4(highlightcolor.rgb * highlightcolor.a + (tcolor.rgb - 0.4 * highlightcolor.a), max(Color.a + 0.25, 0.5));
}
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";
static const char* world3D_ps_main_fog = R"(
#version 150
in vec4 Color;
in vec2 UV;
in vec3 PosW;
@ -282,12 +278,14 @@ static const char* world3D_ps_main_fog = R"(
{
FragColor = desaturate(getFogColor(tcolor * Color));
}
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";
static const char* world3D_ps_main_highlight_fog = R"(
#version 150
in vec4 Color;
in vec2 UV;
in vec3 PosW;
@ -334,12 +332,14 @@ static const char* world3D_ps_main_highlight_fog = R"(
FragColor = vec4(highlightcolor.rgb * highlightcolor.a + (ncolor.rgb - 0.4 * highlightcolor.a), max(ncolor.a + 0.25, 0.5));
}
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";
static const char* world3D_ps_constant_color = R"(
#version 150
in vec4 Color;
in vec2 UV;
@ -350,12 +350,14 @@ static const char* world3D_ps_constant_color = R"(
void main()
{
FragColor = vertexColor;
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";
static const char* world3D_ps_vertex_color = R"(
#version 150
in vec4 Color;
in vec2 UV;
@ -364,12 +366,14 @@ static const char* world3D_ps_vertex_color = R"(
void main()
{
FragColor = Color;
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";
static const char* world3D_ps_lightpass = R"(
#version 150
in vec4 Color;
in vec2 UV;
in vec3 PosW;
@ -438,12 +442,14 @@ static const char* world3D_ps_lightpass = R"(
lightColorMod *= tcolor;
FragColor = desaturate(lightColorMod); //Additive light
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";
static const char* world3D_ps_skybox = R"(
#version 150
in vec3 Tex;
out vec4 FragColor;
@ -456,5 +462,9 @@ static const char* world3D_ps_skybox = R"(
{
vec4 ncolor = texture(texture1, Tex);
FragColor = vec4(highlightcolor.rgb * highlightcolor.a + (ncolor.rgb - 0.4 * highlightcolor.a), 1.0);
#if defined(ALPHA_TEST)
if (FragColor.a < 0.5) discard;
#endif
}
)";

View file

@ -63,24 +63,25 @@ GLuint Texture::GetTexture()
{
if (mTexture == 0)
{
GLint oldActiveTex = GL_TEXTURE0;
glGetIntegerv(GL_ACTIVE_TEXTURE, &oldActiveTex);
glActiveTexture(GL_TEXTURE0);
if (!IsCubeTexture())
{
GLint oldBinding = 0;
glActiveTexture(GL_TEXTURE0);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding);
glGenTextures(1, &mTexture);
glBindTexture(GL_TEXTURE_2D, mTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, !mPixels[0].empty() ? mPixels[0].data() : nullptr);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mWidth, mHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, !mPixels[0].empty() ? mPixels[0].data() : nullptr);
glGenerateMipmap(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, oldBinding);
}
else
{
GLint oldBinding = 0;
glActiveTexture(GL_TEXTURE0);
glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP, &oldBinding);
glGenTextures(1, &mTexture);
@ -93,9 +94,10 @@ GLuint Texture::GetTexture()
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, mWidth, mHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, !mPixels[5].empty() ? mPixels[5].data() : nullptr);
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, oldBinding);
}
glActiveTexture(oldActiveTex);
}
return mTexture;
}