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