[update] Improved the shading of CubeProgram.
This commit is contained in:
parent
79654d6da4
commit
0f17719b79
@ -2,7 +2,8 @@
|
||||
module sj.CubeProgram;
|
||||
|
||||
import std.conv,
|
||||
std.range.primitives;
|
||||
std.range.primitives,
|
||||
std.string;
|
||||
|
||||
import gl4d;
|
||||
|
||||
@ -10,7 +11,27 @@ import gl4d;
|
||||
class CubeProgram {
|
||||
public:
|
||||
///
|
||||
alias Instance = mat4;
|
||||
static struct Material {
|
||||
public:
|
||||
///
|
||||
vec3 diffuse_color = vec3(1, 1, 1);
|
||||
private float padding0_;
|
||||
|
||||
///
|
||||
vec3 specular_color = vec3(1, 1, 1);
|
||||
private float padding1_;
|
||||
|
||||
///
|
||||
vec3 light_color = vec3(1, 1, 1);
|
||||
private float padding2_;
|
||||
///
|
||||
vec3 light_power = vec3(20, 20, 20);
|
||||
private float padding3_;
|
||||
|
||||
///
|
||||
vec3 ambient_color = vec3(0.3, 0.3, 0.3);
|
||||
private float padding4_;
|
||||
}
|
||||
|
||||
///
|
||||
enum ShaderHeader = "#version 330 core
|
||||
@ -18,6 +39,10 @@ class CubeProgram {
|
||||
|
||||
///
|
||||
enum VertexShaderSrc = ShaderHeader ~ q{
|
||||
layout(location = 0) uniform mat4 P;
|
||||
layout(location = 1) uniform mat4 V;
|
||||
layout(location = 2) uniform vec3 lightpos;
|
||||
|
||||
layout(location = 0) in vec3 vert;
|
||||
layout(location = 1) in vec3 normal;
|
||||
|
||||
@ -26,29 +51,63 @@ class CubeProgram {
|
||||
layout(location = 4) in vec4 m3;
|
||||
layout(location = 5) in vec4 m4;
|
||||
|
||||
out vec3 normal_;
|
||||
out vec3 lightdir_;
|
||||
out vec3 normal_;
|
||||
out vec3 eyedir_;
|
||||
out float distance_;
|
||||
|
||||
void main() {
|
||||
mat4 m = transpose(mat4(m1, m2, m3, m4));
|
||||
mat4 M = transpose(mat4(m1, m2, m3, m4));
|
||||
|
||||
normal_ = (m * vec4(normal, 1)).xyz;
|
||||
gl_Position = m * vec4(vert, 1);
|
||||
vec3 lightpos_camera = (V * vec4(lightpos, 1)).xyz;
|
||||
vec3 vert_camera = (V * M * vec4(vert, 1)).xyz;
|
||||
vec3 normal_camera = (V * M * vec4(normal, 0)).xyz;
|
||||
|
||||
eyedir_ = vec3(0, 0, 0) - vert_camera;
|
||||
normal_ = normal_camera;
|
||||
lightdir_ = lightpos_camera + eyedir_;
|
||||
distance_ = length(lightpos_camera - vert_camera);
|
||||
|
||||
gl_Position = P * V * M * vec4(vert, 1);
|
||||
}
|
||||
};
|
||||
///
|
||||
enum FragmentShaderSrc = ShaderHeader ~ q{
|
||||
layout(location = 0) uniform vec3 light_color;
|
||||
layout(location = 1) uniform vec3 light_direction;
|
||||
layout(location = 2) uniform vec3 ambient_color;
|
||||
layout(std140) uniform Material {
|
||||
vec3 diffuse_color;
|
||||
|
||||
in vec3 normal_;
|
||||
vec3 specular_color;
|
||||
|
||||
vec3 light_color;
|
||||
vec3 light_power;
|
||||
|
||||
vec3 ambient_color;
|
||||
} material;
|
||||
|
||||
in vec3 lightdir_;
|
||||
in vec3 normal_;
|
||||
in vec3 eyedir_;
|
||||
in float distance_;
|
||||
|
||||
out vec4 pixel_;
|
||||
|
||||
void main() {
|
||||
float light = dot(normalize(light_direction), normalize(normal_));
|
||||
vec3 color = clamp(light_color * light + ambient_color, 0, 1);
|
||||
vec3 l = normalize(lightdir_);
|
||||
vec3 n = normalize(normal_);
|
||||
|
||||
vec3 e = normalize(eyedir_);
|
||||
vec3 r = reflect(-l, n);
|
||||
|
||||
float diffuse_cos = clamp(dot(l, n), 0, 1);
|
||||
float reflect_cos = clamp(dot(e, r), 0, 1);
|
||||
|
||||
vec3 color_without_ambient =
|
||||
material.diffuse_color * diffuse_cos +
|
||||
material.specular_color * pow(reflect_cos, 5);
|
||||
|
||||
vec3 color =
|
||||
material.ambient_color +
|
||||
color_without_ambient * material.light_color * material.light_power / pow(distance_, 2);
|
||||
pixel_ = vec4(color, 1);
|
||||
}
|
||||
};
|
||||
@ -64,6 +123,18 @@ class CubeProgram {
|
||||
program_ = linker.Link();
|
||||
program_.Validate();
|
||||
|
||||
material_ = UniformBuffer.Create();
|
||||
material_index_ = gl.GetUniformBlockIndex(program_.id, "Material".toStringz);
|
||||
|
||||
material_.Bind();
|
||||
UniformBufferAllocator material_allocator;
|
||||
with (material_allocator) {
|
||||
data = null;
|
||||
size = Material.sizeof;
|
||||
usage = GL_DYNAMIC_DRAW;
|
||||
Allocate(material_);
|
||||
}
|
||||
|
||||
vao_ = VertexArray.Create();
|
||||
verts_ = ArrayBuffer.Create();
|
||||
instances_ = ArrayBuffer.Create();
|
||||
@ -156,28 +227,35 @@ class CubeProgram {
|
||||
ArrayBufferAllocator instances_allocator;
|
||||
with (instances_allocator) {
|
||||
data = null;
|
||||
size = MaxInstanceCount * Instance.sizeof;
|
||||
size = MaxInstanceCount * mat4.sizeof;
|
||||
usage = GL_DYNAMIC_DRAW;
|
||||
Allocate(instances_);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
void Draw(R)(R cubes, vec3 lcolor, vec3 light, vec3 acolor)
|
||||
if (isInputRange!R && is(ElementType!R == Instance)) {
|
||||
void Draw(R)(R cubes, mat4 projection, mat4 view, vec3 lightpos, Material material)
|
||||
if (isInputRange!R && is(ElementType!R == mat4)) {
|
||||
{
|
||||
auto ptr = material_.MapToWrite!Material();
|
||||
*ptr = material;
|
||||
}
|
||||
|
||||
program_.Use();
|
||||
program_.uniform!0 = projection;
|
||||
program_.uniform!1 = view;
|
||||
program_.uniform!2 = lightpos;
|
||||
material_.BindForUniformBlock(material_index_);
|
||||
|
||||
size_t length;
|
||||
{
|
||||
auto ptr = instances_.MapToWrite!Instance();
|
||||
auto ptr = instances_.MapToWrite!mat4();
|
||||
foreach (const ref c; cubes) {
|
||||
assert(length < MaxInstanceCount);
|
||||
ptr[length++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
program_.Use();
|
||||
program_.uniform!0 = lcolor;
|
||||
program_.uniform!1 = light;
|
||||
program_.uniform!2 = acolor;
|
||||
if (length == 0) return;
|
||||
|
||||
vao_.Bind();
|
||||
gl.DrawArraysInstanced(GL_TRIANGLES, 0, 6*6, length.to!int);
|
||||
@ -186,9 +264,13 @@ class CubeProgram {
|
||||
private:
|
||||
ProgramRef program_;
|
||||
|
||||
UniformBufferRef material_;
|
||||
|
||||
VertexArrayRef vao_;
|
||||
|
||||
ArrayBufferRef verts_;
|
||||
|
||||
ArrayBufferRef instances_;
|
||||
|
||||
const GLuint material_index_;
|
||||
}
|
||||
|
@ -14,12 +14,12 @@ import sj.CubeProgram,
|
||||
class LobbyWorld {
|
||||
public:
|
||||
///
|
||||
enum Perspective = mat4.perspective(-0.5, 0.5, -0.5, 0.5, 0.1, 100);
|
||||
enum Projection = mat4.perspective(1, 1, 60, 0.1, 100);
|
||||
|
||||
///
|
||||
this(ProgramSet programs) {
|
||||
background_ = new Background(programs.Get!BackgroundProgram);
|
||||
cube_ = programs.Get!CubeProgram;
|
||||
background_ = new Background(programs.Get!BackgroundProgram);
|
||||
cube_program_ = programs.Get!CubeProgram;
|
||||
}
|
||||
|
||||
///
|
||||
@ -30,9 +30,9 @@ class LobbyWorld {
|
||||
|
||||
gl.Enable(GL_DEPTH_TEST);
|
||||
gl.DepthMask(true);
|
||||
cube_.Draw(
|
||||
cubes.map!(x => Perspective * view * x),
|
||||
light_color, light_direction, ambient_color);
|
||||
cube_program_.Draw(
|
||||
cubes.map!"a.Create()",
|
||||
Projection, view.Create(), light_pos, cube_material);
|
||||
}
|
||||
|
||||
///
|
||||
@ -41,18 +41,16 @@ class LobbyWorld {
|
||||
}
|
||||
|
||||
///
|
||||
mat4[] cubes;
|
||||
ModelMatrixFactory!4[] cubes;
|
||||
///
|
||||
mat4 view = mat4.look_at(vec3(0, 0, -1), vec3(0, 0, 0), vec3(0, 1, 0));
|
||||
ViewMatrixFactory view;
|
||||
///
|
||||
vec3 light_color = vec3(1, 1, 1);
|
||||
vec3 light_pos = vec3(0, 10, 0);
|
||||
///
|
||||
vec3 light_direction = vec3(0, 1, 0);
|
||||
///
|
||||
vec3 ambient_color = vec3(0.1, 0.1, 0.1);
|
||||
CubeProgram.Material cube_material;
|
||||
|
||||
private:
|
||||
Background background_;
|
||||
|
||||
CubeProgram cube_;
|
||||
CubeProgram cube_program_;
|
||||
}
|
||||
|
Reference in New Issue
Block a user