Autogenerated surface shaders
This commit is contained in:
parent
308c39b8f8
commit
3bb458e0ab
@ -105,11 +105,15 @@ set(CLIENT_ONLY_SOURCES
|
|||||||
"src/gfx/frustum.cpp"
|
"src/gfx/frustum.cpp"
|
||||||
"src/gfx/renderer.hpp"
|
"src/gfx/renderer.hpp"
|
||||||
"src/gfx/renderer.cpp"
|
"src/gfx/renderer.cpp"
|
||||||
|
"src/gfx/shader_common.hpp"
|
||||||
"src/gfx/shader_defs.hpp"
|
"src/gfx/shader_defs.hpp"
|
||||||
"src/gfx/shader_sources.hpp"
|
"src/gfx/shader_sources.hpp"
|
||||||
"src/gfx/shader_sources.cpp"
|
"src/gfx/shader_sources.cpp"
|
||||||
"src/gfx/shader.hpp"
|
"src/gfx/shader.hpp"
|
||||||
"src/gfx/shader.cpp"
|
"src/gfx/shader.cpp"
|
||||||
|
"src/gfx/surface_render_flags.hpp"
|
||||||
|
"src/gfx/surface_shader.hpp"
|
||||||
|
"src/gfx/surface_shader.cpp"
|
||||||
"src/gfx/surface.hpp"
|
"src/gfx/surface.hpp"
|
||||||
"src/gfx/texture.cpp"
|
"src/gfx/texture.cpp"
|
||||||
"src/gfx/texture.hpp"
|
"src/gfx/texture.hpp"
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include "assets/skeleton.hpp"
|
#include "assets/skeleton.hpp"
|
||||||
#include "surface.hpp"
|
#include "surface.hpp"
|
||||||
#include "uniform_buffer.hpp"
|
#include "uniform_buffer.hpp"
|
||||||
|
#include "surface_render_flags.hpp"
|
||||||
|
|
||||||
namespace gfx
|
namespace gfx
|
||||||
{
|
{
|
||||||
@ -18,6 +19,7 @@ struct DrawSurfaceCmd
|
|||||||
uint32_t count = 0; // num triangles
|
uint32_t count = 0; // num triangles
|
||||||
float dist = 0.0f; // distance to camera - for transparnt sorting
|
float dist = 0.0f; // distance to camera - for transparnt sorting
|
||||||
const UniformBuffer<glm::mat4>* skinning = nullptr; // skinning matrices for skeletal meshes
|
const UniformBuffer<glm::mat4>* skinning = nullptr; // skinning matrices for skeletal meshes
|
||||||
|
SurfaceRenderFlags rflags = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DrawBeamCmd
|
struct DrawBeamCmd
|
||||||
|
|||||||
@ -14,9 +14,6 @@
|
|||||||
|
|
||||||
gfx::Renderer::Renderer()
|
gfx::Renderer::Renderer()
|
||||||
{
|
{
|
||||||
ShaderSources::MakeShader(mesh_shader_.shader, SS_MESH_VERT, SS_MESH_FRAG);
|
|
||||||
ShaderSources::MakeShader(skel_mesh_shader_.shader, SS_SKEL_MESH_VERT, SS_SKEL_MESH_FRAG);
|
|
||||||
ShaderSources::MakeShader(deform_mesh_shader_.shader, SS_DEFORM_MESH_VERT, SS_DEFORM_MESH_FRAG);
|
|
||||||
ShaderSources::MakeShader(solid_shader_, SS_SOLID_VERT, SS_SOLID_FRAG);
|
ShaderSources::MakeShader(solid_shader_, SS_SOLID_VERT, SS_SOLID_FRAG);
|
||||||
ShaderSources::MakeShader(hud_shader_, SS_HUD_VERT, SS_HUD_FRAG);
|
ShaderSources::MakeShader(hud_shader_, SS_HUD_VERT, SS_HUD_FRAG);
|
||||||
ShaderSources::MakeShader(beam_shader_, SS_BEAM_VERT, SS_BEAM_FRAG);
|
ShaderSources::MakeShader(beam_shader_, SS_BEAM_VERT, SS_BEAM_FRAG);
|
||||||
@ -89,20 +86,32 @@ void gfx::Renderer::SetupBeamVA()
|
|||||||
|
|
||||||
void gfx::Renderer::InvalidateShaders()
|
void gfx::Renderer::InvalidateShaders()
|
||||||
{
|
{
|
||||||
InvalidateMeshShader(mesh_shader_);
|
// invalidate surface shaders
|
||||||
InvalidateMeshShader(skel_mesh_shader_);
|
for (auto& [flags, sshader] : surface_shaders_)
|
||||||
InvalidateMeshShader(deform_mesh_shader_);
|
{
|
||||||
|
InvalidateSurfaceShader(sshader);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx::Renderer::InvalidateMeshShader(MeshShader& mshader)
|
gfx::SurfaceShader& gfx::Renderer::GetSurfaceShader(SurfaceRenderFlags flags)
|
||||||
{
|
{
|
||||||
mshader.global_setup = false;
|
auto it = surface_shaders_.find(flags);
|
||||||
mshader.color = glm::vec4(-1.0f); // invalidate color
|
|
||||||
|
// not yet generated
|
||||||
|
if (it == surface_shaders_.end())
|
||||||
|
{
|
||||||
|
SurfaceShader& sshader = surface_shaders_[flags];
|
||||||
|
sshader.shader = CreateSurfaceShader(flags, sshader.iflags);
|
||||||
|
|
||||||
|
return sshader;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx::Renderer::SetupMeshShader(MeshShader& mshader, const DrawListParams& params)
|
void gfx::Renderer::SetupSurfaceShader(SurfaceShader& sshader, const DrawListParams& params)
|
||||||
{
|
{
|
||||||
const Shader& shader = *mshader.shader;
|
const Shader& shader = *sshader.shader;
|
||||||
|
|
||||||
if (current_shader_ != &shader)
|
if (current_shader_ != &shader)
|
||||||
{
|
{
|
||||||
@ -110,7 +119,7 @@ void gfx::Renderer::SetupMeshShader(MeshShader& mshader, const DrawListParams& p
|
|||||||
current_shader_ = &shader;
|
current_shader_ = &shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mshader.global_setup)
|
if (sshader.global_setup)
|
||||||
{
|
{
|
||||||
return; // Global uniforms are already set up
|
return; // Global uniforms are already set up
|
||||||
}
|
}
|
||||||
@ -118,23 +127,65 @@ void gfx::Renderer::SetupMeshShader(MeshShader& mshader, const DrawListParams& p
|
|||||||
glUniformMatrix4fv(shader.U(gfx::SU_VIEW_PROJ), 1, GL_FALSE, ¶ms.view_proj[0][0]);
|
glUniformMatrix4fv(shader.U(gfx::SU_VIEW_PROJ), 1, GL_FALSE, ¶ms.view_proj[0][0]);
|
||||||
|
|
||||||
// setup lighting
|
// setup lighting
|
||||||
|
if (sshader.iflags & SIF_LIGHTING_DATA)
|
||||||
|
{
|
||||||
glUniform3fv(shader.U(gfx::SU_AMBIENT_LIGHT), 1, ¶ms.env.ambient_light[0]);
|
glUniform3fv(shader.U(gfx::SU_AMBIENT_LIGHT), 1, ¶ms.env.ambient_light[0]);
|
||||||
glUniform3fv(shader.U(gfx::SU_SUN_COLOR), 1, ¶ms.env.sun_color[0]);
|
glUniform3fv(shader.U(gfx::SU_SUN_COLOR), 1, ¶ms.env.sun_color[0]);
|
||||||
glUniform3fv(shader.U(gfx::SU_SUN_DIRECTION), 1, ¶ms.env.sun_direction[0]);
|
glUniform3fv(shader.U(gfx::SU_SUN_DIRECTION), 1, ¶ms.env.sun_direction[0]);
|
||||||
glUniform4fv(shader.U(gfx::SU_FOG), 1, ¶ms.env.fog[0]);
|
// glUniform4fv(shader.U(gfx::SU_FOG), 1, ¶ms.env.fog[0]);
|
||||||
|
}
|
||||||
|
|
||||||
mshader.global_setup = true;
|
sshader.global_setup = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx::Renderer::InvalidateSurfaceShader(SurfaceShader& sshader)
|
||||||
|
{
|
||||||
|
sshader.global_setup = false;
|
||||||
|
sshader.color = glm::vec4(-1.0f); // invalidate color
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawListParams& params)
|
void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawListParams& params)
|
||||||
{
|
{
|
||||||
|
// determine render flags
|
||||||
|
for (auto& cmd : list)
|
||||||
|
{
|
||||||
|
if (cmd.surface->sflags & SF_BLEND)
|
||||||
|
cmd.rflags |= SRF_BLEND;
|
||||||
|
|
||||||
|
if (cmd.surface->texture)
|
||||||
|
cmd.rflags |= SRF_TEXTURE;
|
||||||
|
|
||||||
|
if ((cmd.surface->mflags & MF_SKELETAL) && cmd.skinning)
|
||||||
|
cmd.rflags |= SRF_SKELETAL;
|
||||||
|
|
||||||
|
if ((cmd.surface->sflags & SF_DEFORM_GRID) && cmd.surface->deform_tex)
|
||||||
|
cmd.rflags |= SRF_DEFORM;
|
||||||
|
|
||||||
|
if ((cmd.surface->sflags & SF_UNLIT) == 0)
|
||||||
|
cmd.rflags |= SRF_LIT;
|
||||||
|
|
||||||
|
if (cmd.color)
|
||||||
|
{
|
||||||
|
if (cmd.surface->sflags & SF_OBJECT_COLOR_MULT)
|
||||||
|
cmd.rflags |= SRF_OBJECT_COLOR;
|
||||||
|
else if (cmd.surface->sflags & SF_OBJECT_COLOR)
|
||||||
|
cmd.rflags |= SRF_OBJECT_COLOR | SRF_OBJECT_COLOR_BACKGROUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd.surface->sflags & SF_2SIDED)
|
||||||
|
cmd.rflags |= SRF_2SIDED;
|
||||||
|
|
||||||
|
if (cmd.surface->sflags & SF_BLEND_ADDITIVE)
|
||||||
|
cmd.rflags |= SRF_BLEND_ADDITIVE;
|
||||||
|
|
||||||
|
if ((cmd.surface->sflags & (SF_BLEND | SF_OBJECT_COLOR)) == 0)
|
||||||
|
cmd.rflags |= SRF_CULL_ALPHA;
|
||||||
|
}
|
||||||
|
|
||||||
// sort the list to minimize state changes
|
// sort the list to minimize state changes
|
||||||
std::ranges::sort(list, [](const DrawSurfaceCmd& a, const DrawSurfaceCmd& b) {
|
std::ranges::sort(list, [](const DrawSurfaceCmd& a, const DrawSurfaceCmd& b) {
|
||||||
const Surface* sa = a.surface;
|
const bool blend_a = a.rflags & SRF_BLEND;
|
||||||
const Surface* sb = b.surface;
|
const bool blend_b = b.rflags & SRF_BLEND;
|
||||||
|
|
||||||
const bool blend_a = sa->sflags & SF_BLEND;
|
|
||||||
const bool blend_b = sb->sflags & SF_BLEND;
|
|
||||||
|
|
||||||
if (blend_a != blend_b)
|
if (blend_a != blend_b)
|
||||||
return blend_b; // opaque first
|
return blend_b; // opaque first
|
||||||
@ -144,9 +195,15 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
|
|||||||
return a.dist > b.dist; // do not optimize blended, sort by distance instead
|
return a.dist > b.dist; // do not optimize blended, sort by distance instead
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sa == sb)
|
if (a.surface == b.surface)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (auto cmp = a.rflags <=> b.rflags; cmp != 0)
|
||||||
|
return cmp < 0;
|
||||||
|
|
||||||
|
const auto sa = a.surface;
|
||||||
|
const auto sb = a.surface;
|
||||||
|
|
||||||
if (auto cmp = sa->texture <=> sb->texture; cmp != 0)
|
if (auto cmp = sa->texture <=> sb->texture; cmp != 0)
|
||||||
return cmp < 0;
|
return cmp < 0;
|
||||||
|
|
||||||
@ -162,10 +219,12 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
|
|||||||
glActiveTexture(GL_TEXTURE0); // for all future bindings
|
glActiveTexture(GL_TEXTURE0); // for all future bindings
|
||||||
|
|
||||||
// cache to eliminate fake state changes
|
// cache to eliminate fake state changes
|
||||||
|
SurfaceShader* sshader = nullptr;
|
||||||
const gfx::Texture* last_texture = nullptr;
|
const gfx::Texture* last_texture = nullptr;
|
||||||
const gfx::VertexArray* last_vao = nullptr;
|
const gfx::VertexArray* last_vao = nullptr;
|
||||||
const gfx::UniformBuffer<glm::mat4>* last_skin = nullptr;
|
const gfx::UniformBuffer<glm::mat4>* last_skin = nullptr;
|
||||||
const DeformTexture* last_deform = nullptr;
|
const DeformTexture* last_deform = nullptr;
|
||||||
|
|
||||||
InvalidateShaders();
|
InvalidateShaders();
|
||||||
|
|
||||||
// enable depth test
|
// enable depth test
|
||||||
@ -175,80 +234,76 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
|
|||||||
// reset face culling
|
// reset face culling
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
glCullFace(GL_BACK);
|
glCullFace(GL_BACK);
|
||||||
bool last_twosided = false;
|
|
||||||
|
|
||||||
// reset blending
|
// reset blending
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
bool last_blend = false;
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // set to opacity blending default
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // set to opacity blending default
|
||||||
bool last_blend_additive = false;
|
|
||||||
|
SurfaceRenderFlags last_rflags = 0;
|
||||||
|
|
||||||
for (const DrawSurfaceCmd& cmd : list)
|
for (const DrawSurfaceCmd& cmd : list)
|
||||||
{
|
{
|
||||||
const Surface* surface = cmd.surface;
|
const Surface* surface = cmd.surface;
|
||||||
|
|
||||||
// mesh flags
|
// // mesh flags
|
||||||
const bool skeletal_flag = surface->mflags & MF_SKELETAL;
|
// const bool skeletal_flag = surface->mflags & MF_SKELETAL;
|
||||||
// surface flags
|
// // surface flags
|
||||||
const bool twosided_flag = surface->sflags & SF_2SIDED;
|
//const bool twosided_flag = cmd.rflags & SRF_2SIDED;
|
||||||
const bool blend_flag = surface->sflags & SF_BLEND;
|
// const bool blend_flag = surface->sflags & SF_BLEND;
|
||||||
const bool object_color_flag = surface->sflags & SF_OBJECT_COLOR;
|
// const bool object_color_flag = surface->sflags & SF_OBJECT_COLOR;
|
||||||
const bool object_color_mult_flag = surface->sflags & SF_OBJECT_COLOR_MULT;
|
// const bool object_color_mult_flag = surface->sflags & SF_OBJECT_COLOR_MULT;
|
||||||
const bool deform_flag = surface->sflags & SF_DEFORM_GRID;
|
// const bool deform_flag = surface->sflags & SF_DEFORM_GRID;
|
||||||
const bool unlit_flag = surface->sflags & SF_UNLIT;
|
// const bool unlit_flag = surface->sflags & SF_UNLIT;
|
||||||
|
|
||||||
|
SurfaceRenderFlags rflags_diff = last_rflags ^ cmd.rflags;
|
||||||
|
|
||||||
// sync 2sided
|
// sync 2sided
|
||||||
if (last_twosided != twosided_flag)
|
if (rflags_diff & SRF_2SIDED)
|
||||||
{
|
{
|
||||||
if (twosided_flag)
|
if (cmd.rflags & SRF_2SIDED)
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
else
|
else
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
|
|
||||||
last_twosided = twosided_flag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// select shader
|
// setup shader
|
||||||
MeshShader& mshader = skeletal_flag ? skel_mesh_shader_ : (deform_flag ? deform_mesh_shader_ : mesh_shader_);
|
SurfaceRenderFlags last_shader_rflags = last_rflags & SRF__SHADER;
|
||||||
SetupMeshShader(mshader, params);
|
SurfaceRenderFlags shader_rflags = cmd.rflags & SRF__SHADER;
|
||||||
|
|
||||||
|
if (last_shader_rflags != shader_rflags || !sshader)
|
||||||
|
{
|
||||||
|
sshader = &GetSurfaceShader(shader_rflags);
|
||||||
|
SetupSurfaceShader(*sshader, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto shader = sshader->shader.get();
|
||||||
|
|
||||||
// set model matrix
|
// set model matrix
|
||||||
if (cmd.matrices)
|
if (cmd.matrices)
|
||||||
{
|
{
|
||||||
glUniformMatrix4fv(mshader.shader->U(SU_MODEL), 1, GL_FALSE, &cmd.matrices[0][0][0]);
|
glUniformMatrix4fv(shader->U(SU_MODEL), 1, GL_FALSE, &cmd.matrices[0][0][0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // use identity if no matrix provided
|
{ // use identity if no matrix provided
|
||||||
static const glm::mat4 identity(1.0f);
|
static const glm::mat4 identity(1.0f);
|
||||||
glUniformMatrix4fv(mshader.shader->U(SU_MODEL), 1, GL_FALSE, &identity[0][0]);
|
glUniformMatrix4fv(shader->U(SU_MODEL), 1, GL_FALSE, &identity[0][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set color
|
// sync color
|
||||||
int shflags = SHF_CULL_ALPHA;
|
if (sshader->iflags & SIF_OBJECT_COLOR)
|
||||||
|
|
||||||
glm::vec4 color = glm::vec4(1.0f);
|
|
||||||
if (object_color_flag && cmd.color)
|
|
||||||
{
|
{
|
||||||
// use object color and disable alpha cull
|
if (sshader->color != *cmd.color)
|
||||||
|
|
||||||
if (!object_color_mult_flag)
|
|
||||||
{
|
{
|
||||||
shflags &= ~SHF_CULL_ALPHA;
|
glUniform4fv(shader->U(SU_COLOR), 1, &(*cmd.color)[0]);
|
||||||
shflags |= SHF_BACKGROUND;
|
sshader->color = *cmd.color;
|
||||||
}
|
}
|
||||||
|
|
||||||
color = glm::vec4(*cmd.color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check unlit
|
|
||||||
if (unlit_flag)
|
|
||||||
shflags |= SHF_UNLIT;
|
|
||||||
|
|
||||||
// sync blending
|
// sync blending
|
||||||
if (blend_flag != last_blend)
|
if (rflags_diff & SRF_BLEND)
|
||||||
{
|
{
|
||||||
if (blend_flag)
|
if (cmd.rflags & SRF_BLEND)
|
||||||
{
|
{
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glDepthMask(GL_FALSE);
|
glDepthMask(GL_FALSE);
|
||||||
@ -258,43 +313,19 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
|
|||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
last_blend = blend_flag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sync blending type
|
// sync blending type
|
||||||
if (blend_flag)
|
if ((cmd.rflags & SRF_BLEND) && (rflags_diff & SRF_BLEND_ADDITIVE))
|
||||||
{
|
{
|
||||||
shflags &= ~SHF_CULL_ALPHA;
|
if (cmd.rflags & SRF_BLEND_ADDITIVE)
|
||||||
|
|
||||||
const bool blend_additive = surface->sflags & SF_BLEND_ADDITIVE;
|
|
||||||
if (blend_additive != last_blend_additive)
|
|
||||||
{
|
|
||||||
if (blend_additive)
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||||
else
|
else
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
last_blend_additive = blend_additive;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sync cull_alpha
|
|
||||||
if (mshader.flags != shflags)
|
|
||||||
{
|
|
||||||
glUniform1i(mshader.shader->U(SU_FLAGS), shflags);
|
|
||||||
mshader.flags = shflags;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sync color
|
|
||||||
if (mshader.color != color)
|
|
||||||
{
|
|
||||||
glUniform4fv(mshader.shader->U(SU_COLOR), 1, &color[0]);
|
|
||||||
mshader.color = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind texture
|
// bind texture
|
||||||
if (last_texture != surface->texture.get())
|
if ((sshader->iflags & SIF_COLOR_TEXTURE) && last_texture != surface->texture.get())
|
||||||
{
|
{
|
||||||
GLuint tex_id = surface->texture ? surface->texture->GetId() : 0;
|
GLuint tex_id = surface->texture ? surface->texture->GetId() : 0;
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
@ -303,14 +334,14 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// bind skinning UBO
|
// bind skinning UBO
|
||||||
if (cmd.skinning && last_skin != cmd.skinning)
|
if ((sshader->iflags & SIF_SKELETAL_DATA) && last_skin != cmd.skinning)
|
||||||
{
|
{
|
||||||
glBindBufferBase(GL_UNIFORM_BUFFER, 0, cmd.skinning->GetId());
|
glBindBufferBase(GL_UNIFORM_BUFFER, 0, cmd.skinning->GetId());
|
||||||
last_skin = cmd.skinning;
|
last_skin = cmd.skinning;
|
||||||
}
|
}
|
||||||
|
|
||||||
// bind deform texture
|
// bind deform texture
|
||||||
if (deform_flag && surface->deform_tex.get() != last_deform)
|
if ((sshader->iflags & SIF_DEFORM_DATA) && surface->deform_tex.get() != last_deform)
|
||||||
{
|
{
|
||||||
const auto& deform_tex = *surface->deform_tex;
|
const auto& deform_tex = *surface->deform_tex;
|
||||||
GLuint tex_id = deform_tex.GetId();
|
GLuint tex_id = deform_tex.GetId();
|
||||||
@ -324,7 +355,7 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
|
|||||||
deform_info_mat[0] = deform_info.min;
|
deform_info_mat[0] = deform_info.min;
|
||||||
deform_info_mat[1] = deform_info.max;
|
deform_info_mat[1] = deform_info.max;
|
||||||
deform_info_mat[2] = glm::vec3(deform_info.max_offset, 0.0f, 0.0f);
|
deform_info_mat[2] = glm::vec3(deform_info.max_offset, 0.0f, 0.0f);
|
||||||
glUniformMatrix3fv(mshader.shader->U(SU_DEFORM_INFO), 1, GL_FALSE, &deform_info_mat[0][0]);
|
glUniformMatrix3fv(shader->U(SU_DEFORM_INFO), 1, GL_FALSE, &deform_info_mat[0][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bind VAO
|
// bind VAO
|
||||||
@ -340,6 +371,8 @@ void gfx::Renderer::DrawSurfaceList(std::span<DrawSurfaceCmd> list, const DrawLi
|
|||||||
// draw
|
// draw
|
||||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(num_tris * 3U), GL_UNSIGNED_INT,
|
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(num_tris * 3U), GL_UNSIGNED_INT,
|
||||||
(void*)(first_tri * 3U * sizeof(GLuint)));
|
(void*)(first_tri * 3U * sizeof(GLuint)));
|
||||||
|
|
||||||
|
last_rflags = cmd.rflags;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset this as it is rare and other stuff might not reset this
|
// reset this as it is rare and other stuff might not reset this
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "draw_list.hpp"
|
#include "draw_list.hpp"
|
||||||
#include "shader.hpp"
|
#include "shader.hpp"
|
||||||
|
#include "surface_shader.hpp"
|
||||||
|
|
||||||
namespace gfx
|
namespace gfx
|
||||||
{
|
{
|
||||||
@ -27,14 +28,14 @@ struct DrawListParams
|
|||||||
size_t screen_height = 0;
|
size_t screen_height = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MeshShader
|
struct SurfaceShader
|
||||||
{
|
{
|
||||||
std::unique_ptr<Shader> shader;
|
std::unique_ptr<Shader> shader;
|
||||||
|
SurfaceShaderInputFlags iflags;
|
||||||
|
|
||||||
// cached state to avoid redundant uniform updates which are expensive especially on WebGL
|
// cached state to avoid redundant uniform updates which are expensive especially on WebGL
|
||||||
bool global_setup = false;
|
bool global_setup = false;
|
||||||
glm::vec4 color = glm::vec4(-1.0f); // invalid to force initial setup
|
glm::vec4 color = glm::vec4(-1.0f); // invalid to force initial setup
|
||||||
int flags = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Renderer
|
class Renderer
|
||||||
@ -47,17 +48,17 @@ private:
|
|||||||
void SetupBeamVA();
|
void SetupBeamVA();
|
||||||
|
|
||||||
void InvalidateShaders();
|
void InvalidateShaders();
|
||||||
void InvalidateMeshShader(MeshShader& mshader);
|
|
||||||
void SetupMeshShader(MeshShader& mshader, const DrawListParams& params);
|
SurfaceShader& GetSurfaceShader(SurfaceRenderFlags flags);
|
||||||
|
void SetupSurfaceShader(SurfaceShader& sshader, const DrawListParams& params);
|
||||||
|
void InvalidateSurfaceShader(SurfaceShader& sshader);
|
||||||
|
|
||||||
void DrawSurfaceList(std::span<DrawSurfaceCmd> queue, const DrawListParams& params);
|
void DrawSurfaceList(std::span<DrawSurfaceCmd> queue, const DrawListParams& params);
|
||||||
void DrawBeamList(std::span<DrawBeamCmd> queue, const DrawListParams& params);
|
void DrawBeamList(std::span<DrawBeamCmd> queue, const DrawListParams& params);
|
||||||
void DrawHudList(std::span<DrawHudCmd> queue, const DrawListParams& params);
|
void DrawHudList(std::span<DrawHudCmd> queue, const DrawListParams& params);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MeshShader mesh_shader_;
|
std::map<SurfaceRenderFlags, SurfaceShader> surface_shaders_;
|
||||||
MeshShader skel_mesh_shader_;
|
|
||||||
MeshShader deform_mesh_shader_;
|
|
||||||
std::unique_ptr<Shader> solid_shader_;
|
std::unique_ptr<Shader> solid_shader_;
|
||||||
|
|
||||||
std::unique_ptr<BufferObject> beam_segments_vbo_;
|
std::unique_ptr<BufferObject> beam_segments_vbo_;
|
||||||
|
|||||||
27
src/gfx/shader_common.hpp
Normal file
27
src/gfx/shader_common.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "shader_defs.hpp"
|
||||||
|
#include "client/gl.hpp"
|
||||||
|
|
||||||
|
#ifndef PG_GLES
|
||||||
|
#define GLSL_VERSION \
|
||||||
|
"#version 330 core\n" \
|
||||||
|
"\n"
|
||||||
|
#else
|
||||||
|
#define GLSL_VERSION \
|
||||||
|
"#version 300 es\n" \
|
||||||
|
"precision highp float;\n" \
|
||||||
|
"\n"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define STRINGIFY_HELPER(x) #x
|
||||||
|
#define STRINGIFY(x) STRINGIFY_HELPER(x)
|
||||||
|
|
||||||
|
#define SHADER_DEFS \
|
||||||
|
"#define MAX_LIGHTS " STRINGIFY(SD_MAX_LIGHTS) "\n" \
|
||||||
|
"#define MAX_BONES " STRINGIFY(SD_MAX_BONES) "\n" \
|
||||||
|
"\n"
|
||||||
|
|
||||||
|
#define SHADER_HEADER \
|
||||||
|
GLSL_VERSION \
|
||||||
|
SHADER_DEFS
|
||||||
@ -2,7 +2,3 @@
|
|||||||
|
|
||||||
#define SD_MAX_LIGHTS 4
|
#define SD_MAX_LIGHTS 4
|
||||||
#define SD_MAX_BONES 128
|
#define SD_MAX_BONES 128
|
||||||
|
|
||||||
#define SHF_CULL_ALPHA 1
|
|
||||||
#define SHF_BACKGROUND 2
|
|
||||||
#define SHF_UNLIT 4
|
|
||||||
@ -1,304 +1,9 @@
|
|||||||
#include "shader_sources.hpp"
|
#include "shader_sources.hpp"
|
||||||
#include "shader_defs.hpp"
|
#include "shader_common.hpp"
|
||||||
#include "client/gl.hpp"
|
|
||||||
|
|
||||||
#ifndef PG_GLES
|
|
||||||
#define GLSL_VERSION \
|
|
||||||
"#version 330 core\n" \
|
|
||||||
"\n"
|
|
||||||
#else
|
|
||||||
#define GLSL_VERSION \
|
|
||||||
"#version 300 es\n" \
|
|
||||||
"precision highp float;\n" \
|
|
||||||
"\n"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define STRINGIFY_HELPER(x) #x
|
|
||||||
#define STRINGIFY(x) STRINGIFY_HELPER(x)
|
|
||||||
|
|
||||||
#define SHADER_DEFS \
|
|
||||||
"#define MAX_LIGHTS " STRINGIFY(SD_MAX_LIGHTS) "\n" \
|
|
||||||
"#define MAX_BONES " STRINGIFY(SD_MAX_BONES) "\n" \
|
|
||||||
"#define SHF_CULL_ALPHA " STRINGIFY(SHF_CULL_ALPHA) "\n" \
|
|
||||||
"#define SHF_BACKGROUND " STRINGIFY(SHF_BACKGROUND) "\n" \
|
|
||||||
"#define SHF_UNLIT " STRINGIFY(SHF_UNLIT) "\n" \
|
|
||||||
"\n"
|
|
||||||
|
|
||||||
#define SHADER_HEADER \
|
|
||||||
GLSL_VERSION \
|
|
||||||
SHADER_DEFS
|
|
||||||
|
|
||||||
#define MESH_MATRICES_GLSL R"GLSL(
|
|
||||||
uniform mat4 u_view_proj;
|
|
||||||
uniform mat4 u_model; // Transform matrix
|
|
||||||
)GLSL"
|
|
||||||
|
|
||||||
#define LIGHT_MATRICES_GLSL R"GLSL(
|
|
||||||
uniform vec3 u_ambient_light;
|
|
||||||
uniform vec3 u_sun_direction;
|
|
||||||
uniform vec3 u_sun_color;
|
|
||||||
uniform vec4 u_fog;
|
|
||||||
|
|
||||||
uniform int u_flags;
|
|
||||||
|
|
||||||
uniform int u_num_lights;
|
|
||||||
uniform vec3 u_light_positions[MAX_LIGHTS];
|
|
||||||
uniform vec4 u_light_colors_rs[MAX_LIGHTS]; // rgb = color, a = radius
|
|
||||||
)GLSL"
|
|
||||||
|
|
||||||
#define COMPUTE_LIGHTS_GLSL R"GLSL(
|
|
||||||
// Example sun values (can later be uniforms)
|
|
||||||
//vec3 u_sun_direction = normalize(vec3(0.3, 0.5, -0.8)); // direction from which sunlight comes
|
|
||||||
//vec3 u_sun_color = vec3(1.0, 0.95, 0.7) * 0.9; // warm sunlight color
|
|
||||||
|
|
||||||
//uniform vec3 u_ambient_light;
|
|
||||||
|
|
||||||
vec3 ComputeLights(in vec3 sector_pos, in vec3 sector_normal)
|
|
||||||
{
|
|
||||||
if ((u_flags & SHF_UNLIT) > 0)
|
|
||||||
return vec3(1.0);
|
|
||||||
|
|
||||||
// Base ambient
|
|
||||||
vec3 color = u_ambient_light; //vec3(0.5, 0.5, 0.5) * 0.9; // u_ambient_light
|
|
||||||
|
|
||||||
// Sunlight contribution
|
|
||||||
float sun_dot = max(dot(sector_normal, -u_sun_direction), 0.0);
|
|
||||||
color += u_sun_color * sun_dot;
|
|
||||||
|
|
||||||
// Point lights
|
|
||||||
for (int i = 0; i < u_num_lights; ++i) {
|
|
||||||
vec3 light_pos = u_light_positions[i];
|
|
||||||
vec3 light_color = u_light_colors_rs[i].rgb;
|
|
||||||
float light_radius = u_light_colors_rs[i].a;
|
|
||||||
|
|
||||||
vec3 to_light = light_pos - sector_pos;
|
|
||||||
float dist2 = dot(to_light, to_light);
|
|
||||||
if (dist2 < light_radius * light_radius) {
|
|
||||||
float dist = sqrt(dist2);
|
|
||||||
float attenuation = 1.0 - (dist / light_radius);
|
|
||||||
float dot_term = max(dot(sector_normal, normalize(to_light)), 0.0);
|
|
||||||
color += light_color * dot_term * attenuation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
)GLSL"
|
|
||||||
|
|
||||||
// Zdrojove kody shaderu
|
// Zdrojove kody shaderu
|
||||||
static const char* const s_srcs[] = {
|
static const char* const s_srcs[] = {
|
||||||
|
|
||||||
// SS_MESH_VERT
|
|
||||||
SHADER_HEADER
|
|
||||||
R"GLSL(
|
|
||||||
layout (location = 0) in vec3 a_pos;
|
|
||||||
layout (location = 1) in vec3 a_normal;
|
|
||||||
layout (location = 2) in vec4 a_color;
|
|
||||||
layout (location = 3) in vec2 a_uv;
|
|
||||||
|
|
||||||
)GLSL"
|
|
||||||
MESH_MATRICES_GLSL
|
|
||||||
LIGHT_MATRICES_GLSL
|
|
||||||
COMPUTE_LIGHTS_GLSL
|
|
||||||
R"GLSL(
|
|
||||||
|
|
||||||
out vec2 v_uv;
|
|
||||||
out vec3 v_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 world_pos = u_model * vec4(a_pos, 1.0);
|
|
||||||
vec3 world_normal = normalize(mat3(u_model) * a_normal);
|
|
||||||
gl_Position = u_view_proj * world_pos;
|
|
||||||
|
|
||||||
v_uv = a_uv;
|
|
||||||
v_color = ComputeLights(world_pos.xyz, world_normal) * a_color.rgb;
|
|
||||||
}
|
|
||||||
)GLSL",
|
|
||||||
|
|
||||||
// SS_MESH_FRAG
|
|
||||||
SHADER_HEADER
|
|
||||||
R"GLSL(
|
|
||||||
in vec2 v_uv;
|
|
||||||
in vec3 v_color;
|
|
||||||
|
|
||||||
uniform sampler2D u_tex;
|
|
||||||
uniform vec4 u_color;
|
|
||||||
uniform int u_flags;
|
|
||||||
|
|
||||||
layout (location = 0) out vec4 o_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
o_color = vec4(texture(u_tex, v_uv));
|
|
||||||
|
|
||||||
if ((u_flags & SHF_BACKGROUND) > 0)
|
|
||||||
{
|
|
||||||
o_color = mix(u_color, o_color, o_color.a);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
o_color *= u_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((u_flags & SHF_CULL_ALPHA) > 0)
|
|
||||||
{
|
|
||||||
if (o_color.a < 0.5)
|
|
||||||
discard;
|
|
||||||
}
|
|
||||||
|
|
||||||
o_color.rgb *= v_color; // Apply vertex color
|
|
||||||
//o_color = vec4(1.0, 0.0, 0.0, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
)GLSL",
|
|
||||||
|
|
||||||
// SS_SKEL_MESH_VERT
|
|
||||||
SHADER_HEADER
|
|
||||||
R"GLSL(
|
|
||||||
layout (location = 0) in vec3 a_pos;
|
|
||||||
layout (location = 1) in vec3 a_normal;
|
|
||||||
layout (location = 2) in vec4 a_color;
|
|
||||||
layout (location = 3) in vec2 a_uv;
|
|
||||||
layout (location = 5) in ivec4 a_bone_ids;
|
|
||||||
layout (location = 6) in vec4 a_bone_weights;
|
|
||||||
|
|
||||||
layout (std140) uniform Bones {
|
|
||||||
mat4 u_bone_matrices[MAX_BONES];
|
|
||||||
};
|
|
||||||
|
|
||||||
)GLSL"
|
|
||||||
MESH_MATRICES_GLSL
|
|
||||||
LIGHT_MATRICES_GLSL
|
|
||||||
COMPUTE_LIGHTS_GLSL
|
|
||||||
R"GLSL(
|
|
||||||
|
|
||||||
out vec2 v_uv;
|
|
||||||
out vec3 v_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
mat4 bone_transform = mat4(0.0);
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
int bone_id = a_bone_ids[i];
|
|
||||||
if (bone_id >= 0) {
|
|
||||||
bone_transform += u_bone_matrices[bone_id] * a_bone_weights[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 world_pos = bone_transform * vec4(a_pos, 1.0);
|
|
||||||
vec3 world_normal = normalize(mat3(bone_transform) * a_normal);
|
|
||||||
gl_Position = u_view_proj * world_pos;
|
|
||||||
|
|
||||||
v_uv = a_uv;
|
|
||||||
v_color = ComputeLights(world_pos.xyz, world_normal) * a_color.rgb;
|
|
||||||
}
|
|
||||||
)GLSL",
|
|
||||||
|
|
||||||
// SS_SKEL_MESH_FRAG
|
|
||||||
SHADER_HEADER
|
|
||||||
R"GLSL(
|
|
||||||
in vec2 v_uv;
|
|
||||||
in vec3 v_color;
|
|
||||||
|
|
||||||
uniform sampler2D u_tex;
|
|
||||||
uniform vec4 u_color;
|
|
||||||
uniform int u_flags;
|
|
||||||
|
|
||||||
layout (location = 0) out vec4 o_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
o_color = vec4(texture(u_tex, v_uv));
|
|
||||||
|
|
||||||
if ((u_flags & SHF_BACKGROUND) > 0)
|
|
||||||
{
|
|
||||||
o_color = mix(u_color, o_color, o_color.a);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
o_color *= u_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((u_flags & SHF_CULL_ALPHA) > 0)
|
|
||||||
{
|
|
||||||
if (o_color.a < 0.5)
|
|
||||||
discard;
|
|
||||||
}
|
|
||||||
|
|
||||||
o_color.rgb *= v_color; // Apply vertex color
|
|
||||||
//o_color = vec4(1.0, 0.0, 0.0, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
)GLSL",
|
|
||||||
|
|
||||||
// SS_DEFORM_MESH_VERT
|
|
||||||
SHADER_HEADER
|
|
||||||
R"GLSL(
|
|
||||||
layout (location = 0) in vec3 a_pos;
|
|
||||||
layout (location = 1) in vec3 a_normal;
|
|
||||||
layout (location = 2) in vec4 a_color;
|
|
||||||
layout (location = 3) in vec2 a_uv;
|
|
||||||
|
|
||||||
)GLSL"
|
|
||||||
MESH_MATRICES_GLSL
|
|
||||||
LIGHT_MATRICES_GLSL
|
|
||||||
COMPUTE_LIGHTS_GLSL
|
|
||||||
R"GLSL(
|
|
||||||
|
|
||||||
uniform mediump sampler3D u_deform_tex;
|
|
||||||
uniform mat3 u_deform_info;
|
|
||||||
|
|
||||||
out vec2 v_uv;
|
|
||||||
out vec3 v_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec3 deform_pos = (a_pos - u_deform_info[0]) / (u_deform_info[1] - u_deform_info[0]);
|
|
||||||
vec3 pos = a_pos + texture(u_deform_tex, deform_pos).xyz * u_deform_info[2].x;
|
|
||||||
//vec3 pos = a_pos + u_deform_info[0] * u_deform_info[2].x;
|
|
||||||
//vec3 pos = a_pos + vec3(0.0, 0.0, 1.0);
|
|
||||||
|
|
||||||
vec4 world_pos = u_model * vec4(pos, 1.0);
|
|
||||||
vec3 world_normal = normalize(mat3(u_model) * a_normal);
|
|
||||||
gl_Position = u_view_proj * world_pos;
|
|
||||||
|
|
||||||
v_uv = a_uv;
|
|
||||||
v_color = ComputeLights(world_pos.xyz, world_normal) * a_color.rgb;
|
|
||||||
}
|
|
||||||
)GLSL",
|
|
||||||
|
|
||||||
// SS_DEFORM_MESH_FRAG
|
|
||||||
SHADER_HEADER
|
|
||||||
R"GLSL(
|
|
||||||
in vec2 v_uv;
|
|
||||||
in vec3 v_color;
|
|
||||||
|
|
||||||
uniform sampler2D u_tex;
|
|
||||||
uniform vec4 u_color;
|
|
||||||
uniform int u_flags;
|
|
||||||
|
|
||||||
layout (location = 0) out vec4 o_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
o_color = vec4(texture(u_tex, v_uv));
|
|
||||||
|
|
||||||
if ((u_flags & SHF_BACKGROUND) > 0)
|
|
||||||
{
|
|
||||||
o_color = mix(u_color, o_color, o_color.a);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
o_color *= u_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((u_flags & SHF_CULL_ALPHA) > 0)
|
|
||||||
{
|
|
||||||
if (o_color.a < 0.5)
|
|
||||||
discard;
|
|
||||||
}
|
|
||||||
|
|
||||||
o_color.rgb *= v_color; // Apply vertex color
|
|
||||||
//o_color = vec4(1.0, 0.0, 0.0, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
)GLSL",
|
|
||||||
|
|
||||||
// SS_SOLID_VERT
|
// SS_SOLID_VERT
|
||||||
SHADER_HEADER
|
SHADER_HEADER
|
||||||
R"GLSL(
|
R"GLSL(
|
||||||
|
|||||||
@ -7,15 +7,6 @@ namespace gfx
|
|||||||
{
|
{
|
||||||
enum ShaderSource
|
enum ShaderSource
|
||||||
{
|
{
|
||||||
SS_MESH_VERT,
|
|
||||||
SS_MESH_FRAG,
|
|
||||||
|
|
||||||
SS_SKEL_MESH_VERT,
|
|
||||||
SS_SKEL_MESH_FRAG,
|
|
||||||
|
|
||||||
SS_DEFORM_MESH_VERT,
|
|
||||||
SS_DEFORM_MESH_FRAG,
|
|
||||||
|
|
||||||
SS_SOLID_VERT,
|
SS_SOLID_VERT,
|
||||||
SS_SOLID_FRAG,
|
SS_SOLID_FRAG,
|
||||||
|
|
||||||
|
|||||||
32
src/gfx/surface_render_flags.hpp
Normal file
32
src/gfx/surface_render_flags.hpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace gfx
|
||||||
|
{
|
||||||
|
|
||||||
|
using SurfaceRenderFlags = uint16_t;
|
||||||
|
|
||||||
|
enum SurfaceRenderFlag : SurfaceRenderFlags
|
||||||
|
{
|
||||||
|
// dont require shader switch
|
||||||
|
SRF_BLEND_ADDITIVE = 1,
|
||||||
|
SRF_2SIDED = 2,
|
||||||
|
|
||||||
|
// require shader switch
|
||||||
|
SRF_CULL_ALPHA = 4,
|
||||||
|
SRF_OBJECT_COLOR = 8,
|
||||||
|
SRF_OBJECT_COLOR_BACKGROUND = 16,
|
||||||
|
SRF_LIT = 32,
|
||||||
|
SRF_DEFORM = 64,
|
||||||
|
SRF_SKELETAL = 128,
|
||||||
|
SRF_TEXTURE = 256,
|
||||||
|
|
||||||
|
SRF__SHADER = SRF_CULL_ALPHA | SRF_OBJECT_COLOR | SRF_OBJECT_COLOR_BACKGROUND | SRF_LIT | SRF_SKELETAL | SRF_DEFORM | SRF_TEXTURE,
|
||||||
|
|
||||||
|
// order affects visual result
|
||||||
|
SRF_BLEND = 512,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
189
src/gfx/surface_shader.cpp
Normal file
189
src/gfx/surface_shader.cpp
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
#include "surface_shader.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "shader_common.hpp"
|
||||||
|
|
||||||
|
std::unique_ptr<gfx::Shader> gfx::CreateSurfaceShader(SurfaceRenderFlags flags, SurfaceShaderInputFlags& input_flags)
|
||||||
|
{
|
||||||
|
std::string vert_attributes, vert_uniforms, vert_outs, vert_funcs, vert_pos_calc, vert_main;
|
||||||
|
std::string frag_ins, frag_uniforms, frag_funcs, frag_main;
|
||||||
|
|
||||||
|
// default unlit untextured skeleton
|
||||||
|
|
||||||
|
vert_attributes = R"GLSL(
|
||||||
|
layout (location = 0) in vec3 a_pos;
|
||||||
|
layout (location = 1) in vec3 a_normal;
|
||||||
|
layout (location = 2) in vec4 a_color;
|
||||||
|
layout (location = 3) in vec2 a_uv;
|
||||||
|
)GLSL";
|
||||||
|
|
||||||
|
vert_uniforms = R"GLSL(
|
||||||
|
uniform mat4 u_view_proj;
|
||||||
|
uniform mat4 u_model;
|
||||||
|
)GLSL";
|
||||||
|
|
||||||
|
vert_outs = R"GLSL(
|
||||||
|
out vec3 v_color;
|
||||||
|
)GLSL";
|
||||||
|
|
||||||
|
vert_pos_calc = R"GLSL(
|
||||||
|
vec4 world_pos = u_model * vec4(a_pos, 1.0);
|
||||||
|
vec3 world_normal = normalize(mat3(u_model) * a_normal);
|
||||||
|
)GLSL";
|
||||||
|
|
||||||
|
vert_main = R"GLSL(
|
||||||
|
gl_Position = u_view_proj * world_pos;
|
||||||
|
v_color = a_color.rgb;
|
||||||
|
)GLSL";
|
||||||
|
|
||||||
|
frag_ins = R"GLSL(
|
||||||
|
in vec3 v_color;
|
||||||
|
)GLSL";
|
||||||
|
|
||||||
|
frag_main = R"GLSL(
|
||||||
|
o_color = vec4(1.0);
|
||||||
|
)GLSL";
|
||||||
|
|
||||||
|
input_flags = 0;
|
||||||
|
|
||||||
|
// color texture
|
||||||
|
if (flags & SRF_TEXTURE)
|
||||||
|
{
|
||||||
|
vert_outs += "out vec2 v_uv;\n";
|
||||||
|
vert_main += "v_uv = a_uv;\n";
|
||||||
|
|
||||||
|
frag_ins += "in vec2 v_uv;\n";
|
||||||
|
frag_uniforms += "uniform sampler2D u_tex;\n";
|
||||||
|
frag_main += "o_color *= texture(u_tex, v_uv);\n";
|
||||||
|
|
||||||
|
input_flags |= SIF_COLOR_TEXTURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// any object color type
|
||||||
|
if (flags & (SRF_OBJECT_COLOR | SRF_OBJECT_COLOR_BACKGROUND))
|
||||||
|
{
|
||||||
|
frag_uniforms += "uniform vec4 u_color;\n";
|
||||||
|
|
||||||
|
if (flags & SRF_OBJECT_COLOR_BACKGROUND)
|
||||||
|
{
|
||||||
|
frag_main += "o_color = mix(u_color, o_color, o_color.a);\n";
|
||||||
|
}
|
||||||
|
else // just multiply
|
||||||
|
{
|
||||||
|
frag_main += "o_color *= u_color;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
input_flags |= SIF_OBJECT_COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// alpha culling
|
||||||
|
if (flags & SRF_CULL_ALPHA)
|
||||||
|
{
|
||||||
|
frag_main += "if (o_color.a < 0.5) discard;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// lighting
|
||||||
|
if (flags & SRF_LIT)
|
||||||
|
{
|
||||||
|
vert_uniforms += R"GLSL(
|
||||||
|
// global
|
||||||
|
uniform vec3 u_ambient_light;
|
||||||
|
uniform vec3 u_sun_direction;
|
||||||
|
uniform vec3 u_sun_color;
|
||||||
|
|
||||||
|
// local
|
||||||
|
uniform int u_num_lights;
|
||||||
|
uniform vec3 u_light_positions[MAX_LIGHTS];
|
||||||
|
uniform vec4 u_light_colors_rs[MAX_LIGHTS]; // rgb = color, a = radius
|
||||||
|
)GLSL";
|
||||||
|
|
||||||
|
vert_funcs += R"GLSL(
|
||||||
|
vec3 ComputeLights(in vec3 sector_pos, in vec3 sector_normal)
|
||||||
|
{
|
||||||
|
// Base ambient
|
||||||
|
vec3 color = u_ambient_light;
|
||||||
|
|
||||||
|
// Sunlight contribution
|
||||||
|
float sun_dot = max(dot(sector_normal, -u_sun_direction), 0.0);
|
||||||
|
color += u_sun_color * sun_dot;
|
||||||
|
|
||||||
|
// Point lights
|
||||||
|
for (int i = 0; i < u_num_lights; ++i) {
|
||||||
|
vec3 light_pos = u_light_positions[i];
|
||||||
|
vec3 light_color = u_light_colors_rs[i].rgb;
|
||||||
|
float light_radius = u_light_colors_rs[i].a;
|
||||||
|
|
||||||
|
vec3 to_light = light_pos - sector_pos;
|
||||||
|
float dist2 = dot(to_light, to_light);
|
||||||
|
if (dist2 < light_radius * light_radius) {
|
||||||
|
float dist = sqrt(dist2);
|
||||||
|
float attenuation = 1.0 - (dist / light_radius);
|
||||||
|
float dot_term = max(dot(sector_normal, normalize(to_light)), 0.0);
|
||||||
|
color += light_color * dot_term * attenuation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
)GLSL";
|
||||||
|
|
||||||
|
vert_main += "v_color *= ComputeLights(world_pos.xyz, world_normal);\n";
|
||||||
|
|
||||||
|
input_flags |= SIF_LIGHTING_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & SRF_SKELETAL) // skeletal deform
|
||||||
|
{
|
||||||
|
vert_attributes += R"GLSL(
|
||||||
|
layout (location = 5) in ivec4 a_bone_ids;
|
||||||
|
layout (location = 6) in vec4 a_bone_weights;
|
||||||
|
)GLSL";
|
||||||
|
|
||||||
|
vert_uniforms += R"GLSL(
|
||||||
|
layout (std140) uniform Bones {
|
||||||
|
mat4 u_bone_matrices[MAX_BONES];
|
||||||
|
};
|
||||||
|
)GLSL";
|
||||||
|
|
||||||
|
vert_pos_calc = R"GLSL(
|
||||||
|
mat4 bone_transform = mat4(0.0);
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
int bone_id = a_bone_ids[i];
|
||||||
|
if (bone_id >= 0) {
|
||||||
|
bone_transform += u_bone_matrices[bone_id] * a_bone_weights[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 world_pos = bone_transform * vec4(a_pos, 1.0);
|
||||||
|
vec3 world_normal = normalize(mat3(bone_transform) * a_normal);
|
||||||
|
)GLSL";
|
||||||
|
|
||||||
|
input_flags |= SIF_SKELETAL_DATA;
|
||||||
|
}
|
||||||
|
else if (flags & SRF_DEFORM) // grid deform
|
||||||
|
{
|
||||||
|
vert_uniforms += R"GLSL(
|
||||||
|
uniform mediump sampler3D u_deform_tex;
|
||||||
|
uniform mat3 u_deform_info;
|
||||||
|
)GLSL";
|
||||||
|
|
||||||
|
vert_pos_calc = R"GLSL(
|
||||||
|
vec3 deform_pos = (a_pos - u_deform_info[0]) / (u_deform_info[1] - u_deform_info[0]);
|
||||||
|
vec3 pos = a_pos + texture(u_deform_tex, deform_pos).xyz * u_deform_info[2].x;
|
||||||
|
|
||||||
|
vec4 world_pos = u_model * vec4(pos, 1.0);
|
||||||
|
vec3 world_normal = normalize(mat3(u_model) * a_normal);
|
||||||
|
)GLSL";
|
||||||
|
|
||||||
|
input_flags |= SIF_DEFORM_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
frag_main += "o_color.rgb *= v_color;";
|
||||||
|
vert_main = vert_pos_calc + vert_main;
|
||||||
|
|
||||||
|
std::string vertex_src = SHADER_HEADER + vert_attributes + vert_uniforms + vert_outs + vert_funcs + "\nvoid main() {\n" + vert_main + "\n}\n";
|
||||||
|
std::string fragment_src = SHADER_HEADER + frag_ins + frag_uniforms + "\nlayout (location = 0) out vec4 o_color;\n" + frag_funcs + "\nvoid main() {\n" + frag_main + "\n}\n";
|
||||||
|
|
||||||
|
return std::make_unique<Shader>(vertex_src.c_str(), fragment_src.c_str());
|
||||||
|
}
|
||||||
25
src/gfx/surface_shader.hpp
Normal file
25
src/gfx/surface_shader.hpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include "shader.hpp"
|
||||||
|
#include "surface_render_flags.hpp"
|
||||||
|
|
||||||
|
namespace gfx
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
using SurfaceShaderInputFlags = uint8_t;
|
||||||
|
|
||||||
|
enum SurfaceShaderInputFlag : SurfaceShaderInputFlags
|
||||||
|
{
|
||||||
|
SIF_COLOR_TEXTURE = 1,
|
||||||
|
SIF_OBJECT_COLOR = 2,
|
||||||
|
SIF_LIGHTING_DATA = 4,
|
||||||
|
SIF_SKELETAL_DATA = 8,
|
||||||
|
SIF_DEFORM_DATA = 16,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<Shader> CreateSurfaceShader(SurfaceRenderFlags flags, SurfaceShaderInputFlags& input_flags);
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user