[add] Added CubeProgram.

This commit is contained in:
falsycat 2019-10-11 00:00:00 +00:00
parent 361678a94f
commit 58e88e9eb4
4 changed files with 254 additions and 8 deletions

View File

@ -23,7 +23,7 @@ class AbstractGame {
} }
/// ///
void Draw() { void Draw() {
gl.Clear(GL_COLOR_BUFFER_BIT); gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
scene_.Draw(); scene_.Draw();
} }

194
src/sj/CubeProgram.d Normal file
View File

@ -0,0 +1,194 @@
/// License: MIT
module sj.CubeProgram;
import std.conv,
std.range.primitives;
import gl4d;
///
class CubeProgram {
public:
///
alias Instance = mat4;
///
enum ShaderHeader = "#version 330 core
#extension GL_ARB_explicit_uniform_location : enable";
///
enum VertexShaderSrc = ShaderHeader ~ q{
layout(location = 0) in vec3 vert;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec4 m1;
layout(location = 3) in vec4 m2;
layout(location = 4) in vec4 m3;
layout(location = 5) in vec4 m4;
out vec3 normal_;
void main() {
mat4 m = transpose(mat4(m1, m2, m3, m4));
normal_ = (m * vec4(normal, 1)).xyz;
gl_Position = 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;
in vec3 normal_;
out vec4 pixel_;
void main() {
float light = dot(normalize(light_direction), normalize(normal_));
vec3 color = clamp(light_color * light + ambient_color, 0, 1);
pixel_ = vec4(color, 1);
}
};
///
enum MaxInstanceCount = 10;
///
this() {
ProgramLinker linker;
linker.vertex = VertexShader.Compile(VertexShaderSrc);
linker.fragment = FragmentShader.Compile(FragmentShaderSrc);
program_ = linker.Link();
program_.Validate();
vao_ = VertexArray.Create();
verts_ = ArrayBuffer.Create();
instances_ = ArrayBuffer.Create();
vao_.Bind();
VertexArrayAttacher attacher;
with (attacher) {
index = 0;
type = GL_FLOAT;
offset = vec3.sizeof * 0;
stride = vec3.sizeof * 2;
dimension = 3;
Attach(vao_, verts_);
index = 1;
type = GL_FLOAT;
offset = vec3.sizeof * 1;
stride = vec3.sizeof * 2;
dimension = 3;
Attach(vao_, verts_);
index = 2;
type = GL_FLOAT;
offset = vec4.sizeof * 0;
stride = vec4.sizeof * 4;
dimension = 4;
divisor = 1;
Attach(vao_, instances_);
index = 3;
offset += vec4.sizeof;
Attach(vao_, instances_);
index = 4;
offset += vec4.sizeof;
Attach(vao_, instances_);
index = 5;
offset += vec4.sizeof;
Attach(vao_, instances_);
}
verts_.Bind();
ArrayBufferAllocator verts_allocator;
with (verts_allocator) {
enum v = [
// left
vec3(-1, 1, -1), vec3(-1, 1, 1), vec3(-1, -1, 1),
vec3(-1, 1, -1), vec3(-1, -1, -1), vec3(-1, -1, 1),
// right
vec3(1, 1, -1), vec3(1, 1, 1), vec3(1, -1, 1),
vec3(1, 1, -1), vec3(1, -1, -1), vec3(1, -1, 1),
// top
vec3(-1, 1, -1), vec3(-1, 1, 1), vec3(1, 1, 1),
vec3(-1, 1, -1), vec3( 1, 1, -1), vec3(1, 1, 1),
// bottom
vec3(-1, -1, -1), vec3(-1, -1, 1), vec3(1, -1, 1),
vec3(-1, -1, -1), vec3( 1, -1, -1), vec3(1, -1, 1),
// front
vec3(-1, 1, -1), vec3( 1, 1, -1), vec3(1, -1, -1),
vec3(-1, 1, -1), vec3(-1, -1, -1), vec3(1, -1, -1),
// back
vec3(-1, 1, 1), vec3( 1, 1, 1), vec3(1, -1, 1),
vec3(-1, 1, 1), vec3(-1, -1, 1), vec3(1, -1, 1),
];
enum n = [
vec3(-1, 0, 0), // left
vec3( 1, 0, 0), // right
vec3( 0, 1, 0), // top
vec3( 0, -1, 0), // bottom
vec3( 0, 0, -1), // front
vec3( 0, 0, 1), // back
];
enum d = {
vec3[] d;
foreach (i, p; v) d ~= [p, n[i/6]];
return d;
}();
const d_mem = d;
data = d_mem.ptr;
size = d_mem[0].sizeof * d_mem.length;
usage = GL_STATIC_DRAW;
Allocate(verts_);
}
instances_.Bind();
ArrayBufferAllocator instances_allocator;
with (instances_allocator) {
data = null;
size = MaxInstanceCount * Instance.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)) {
size_t length;
{
auto ptr = instances_.MapToWrite!Instance();
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;
vao_.Bind();
gl.DrawArraysInstanced(GL_TRIANGLES, 0, 6*6, length.to!int);
}
private:
ProgramRef program_;
VertexArrayRef vao_;
ArrayBufferRef verts_;
ArrayBufferRef instances_;
}

View File

@ -1,21 +1,38 @@
/// License: MIT /// License: MIT
module sj.LobbyWorld; module sj.LobbyWorld;
import std.algorithm;
import gl4d;
import sjplayer.Background; import sjplayer.Background;
import sj.ProgramSet; import sj.CubeProgram,
sj.ProgramSet;
/// ///
class LobbyWorld { class LobbyWorld {
public: public:
///
enum Perspective = mat4.perspective(-0.5, 0.5, -0.5, 0.5, 0.1, 100);
/// ///
this(ProgramSet programs) { this(ProgramSet programs) {
background_ = new Background(programs.forPlayers.Get!BackgroundProgram); background_ = new Background(programs.Get!BackgroundProgram);
cube_ = programs.Get!CubeProgram;
} }
/// ///
void Draw() { void Draw() {
gl.Disable(GL_DEPTH_TEST);
gl.DepthMask(false);
background_.Draw(); background_.Draw();
gl.Enable(GL_DEPTH_TEST);
gl.DepthMask(true);
cube_.Draw(
cubes.map!(x => Perspective * view * x),
light_color, light_direction, ambient_color);
} }
/// ///
@ -23,6 +40,19 @@ class LobbyWorld {
return background_; return background_;
} }
///
mat4[] cubes;
///
mat4 view = mat4.look_at(vec3(0, 0, -1), vec3(0, 0, 0), vec3(0, 1, 0));
///
vec3 light_color = vec3(1, 1, 1, 1);
///
vec3 light_direction = vec3(0, 1, 0);
///
vec3 ambient_color = vec3(0.1, 0.1, 0.1);
private: private:
Background background_; Background background_;
CubeProgram cube_;
} }

View File

@ -1,24 +1,46 @@
/// License: MIT /// License: MIT
module sj.ProgramSet; module sj.ProgramSet;
import std.meta,
std.typecons;
static import sjplayer = sjplayer.ProgramSet; static import sjplayer = sjplayer.ProgramSet;
import sj.CubeProgram;
/// ///
class ProgramSet { class ProgramSet {
public: public:
alias Programs = Tuple!(
CubeProgram,
);
/// ///
this() { this() {
for_players_ = new sjplayer.ProgramSet; for_player_ = new sjplayer.ProgramSet;
foreach (ref p; programs_) {
p = new typeof(p);
}
} }
~this() { ~this() {
for_players_.destroy(); for_player_.destroy();
foreach (p; programs_) {
p.destroy();
}
} }
/// ///
@property sjplayer.ProgramSet forPlayers() { T Get(T)() {
return for_players_; enum index = staticIndexOf!(T, Programs.Types);
static if (index >= 0) {
return programs_[index];
} else {
return for_player_.Get!T;
}
} }
private: private:
sjplayer.ProgramSet for_players_; sjplayer.ProgramSet for_player_;
Programs programs_;
} }