Merges thirdparty modules into this repo.
This commit is contained in:
1
thirdparty/gl4d
vendored
1
thirdparty/gl4d
vendored
Submodule thirdparty/gl4d deleted from 33883a68a9
8
thirdparty/gl4d/.gitignore
vendored
Normal file
8
thirdparty/gl4d/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/.bin
|
||||
/.dub
|
||||
/dub.selections.json
|
||||
|
||||
/docs
|
||||
/docs.json
|
||||
|
||||
*.swp
|
13
thirdparty/gl4d/dub.json
vendored
Normal file
13
thirdparty/gl4d/dub.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "gl4d",
|
||||
"license": "MIT",
|
||||
|
||||
"targetType": "library",
|
||||
"targetPath": ".bin",
|
||||
|
||||
"dependencies": {
|
||||
"bindbc-opengl": "~>0.9.0",
|
||||
"gl3n": "~>1.3.1"
|
||||
},
|
||||
"versions": ["GL_33"]
|
||||
}
|
164
thirdparty/gl4d/src/gl4d/Buffer.d
vendored
Normal file
164
thirdparty/gl4d/src/gl4d/Buffer.d
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
/// License: MIT
|
||||
module gl4d.Buffer;
|
||||
|
||||
import std.conv,
|
||||
std.typecons;
|
||||
|
||||
import gl4d.gl,
|
||||
gl4d.math,
|
||||
gl4d.GLObject;
|
||||
|
||||
///
|
||||
alias ArrayBuffer = Buffer!GL_ARRAY_BUFFER;
|
||||
/// RefCounted version of ArrayBuffer.
|
||||
alias ArrayBufferRef = BufferRef!GL_ARRAY_BUFFER;
|
||||
///
|
||||
alias ArrayBufferAllocator = BufferAllocator!GL_ARRAY_BUFFER;
|
||||
///
|
||||
alias ArrayBufferOverwriter = BufferOverwriter!GL_ARRAY_BUFFER;
|
||||
|
||||
///
|
||||
alias ElementArrayBuffer = Buffer!GL_ELEMENT_ARRAY_BUFFER;
|
||||
/// RefCounted version of ElementArrayBuffer.
|
||||
alias ElementArrayBufferRef = BufferRef!GL_ELEMENT_ARRAY_BUFFER;
|
||||
///
|
||||
alias ElementArrayBufferAllocator = BufferAllocator!GL_ELEMENT_ARRAY_BUFFER;
|
||||
///
|
||||
alias ElementArrayBufferOverwriter = BufferOverwriter!GL_ELEMENT_ARRAY_BUFFER;
|
||||
|
||||
///
|
||||
alias UniformBuffer = Buffer!GL_UNIFORM_BUFFER;
|
||||
/// RefCounted version of UniformBuffer.
|
||||
alias UniformBufferRef = BufferRef!GL_UNIFORM_BUFFER;
|
||||
///
|
||||
alias UniformBufferAllocator = BufferAllocator!GL_UNIFORM_BUFFER;
|
||||
///
|
||||
alias UniformBufferOverwriter = BufferOverwriter!GL_UNIFORM_BUFFER;
|
||||
|
||||
/// RefCounted version of Buffer.
|
||||
template BufferRef(GLenum target) {
|
||||
alias BufferRef = RefCounted!(Buffer!target);
|
||||
}
|
||||
|
||||
/// A wrapper type for OpenGL buffer.
|
||||
///
|
||||
/// Usually this is wrapped by RefCounted.
|
||||
/// When it's in default, empty() property returns true and id() property is invalid.
|
||||
struct Buffer(GLenum target_) {
|
||||
mixin GLObject!(
|
||||
(x, y) => gl.GenBuffers(x, y),
|
||||
(x) => gl.BindBuffer(target_, x),
|
||||
(x) => gl.DeleteTextures(1, x)
|
||||
);
|
||||
|
||||
public:
|
||||
///
|
||||
enum target = target_;
|
||||
|
||||
/// Binds this buffer to be written by transform feedbacks.
|
||||
static if (target_ == GL_ARRAY_BUFFER)
|
||||
void BindForTransformFeedback(int index) {
|
||||
assert(!empty);
|
||||
gl.BindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, index.to!GLuint, id);
|
||||
}
|
||||
|
||||
/// Binds this buffer to the uniform block.
|
||||
static if (target_ == GL_UNIFORM_BUFFER)
|
||||
void BindForUniformBlock(int index) {
|
||||
assert(!empty);
|
||||
gl.BindBufferBase(GL_UNIFORM_BUFFER, index.to!GLuint, id);
|
||||
}
|
||||
}
|
||||
|
||||
/// An allocator for buffers.
|
||||
struct BufferAllocator(GLenum target) {
|
||||
public:
|
||||
///
|
||||
size_t size;
|
||||
///
|
||||
const(void)* data;
|
||||
///
|
||||
GLenum usage = GL_STATIC_DRAW;
|
||||
|
||||
/// Allocates the buffer with parameters this has.
|
||||
///
|
||||
/// Binds the buffer automatically.
|
||||
void Allocate(ref BufferRef!target buffer)
|
||||
in {
|
||||
assert(!buffer.empty);
|
||||
assert(size > 0);
|
||||
}
|
||||
do {
|
||||
buffer.Bind();
|
||||
gl.BufferData(target, size.to!GLsizeiptr, data, usage);
|
||||
}
|
||||
}
|
||||
|
||||
/// An overwriter for buffers.
|
||||
struct BufferOverwriter(GLenum target) {
|
||||
public:
|
||||
///
|
||||
size_t offset;
|
||||
///
|
||||
size_t size;
|
||||
///
|
||||
const(void)* data;
|
||||
|
||||
/// Overwrites the buffer with parameters this has.
|
||||
///
|
||||
/// The buffer will be bound automatically.
|
||||
void Overwrite(ref BufferRef!target buffer)
|
||||
in {
|
||||
assert(!buffer.empty);
|
||||
|
||||
assert(offset >= 0);
|
||||
assert(size > 0);
|
||||
}
|
||||
do {
|
||||
buffer.Bind();
|
||||
gl.BufferSubData(target, offset.to!GLintptr, size.to!GLsizeiptr, data);
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes the buffer's data pointer.
|
||||
///
|
||||
/// T must be a BufferRef type.
|
||||
///
|
||||
/// The buffer will be bound automatically.
|
||||
///
|
||||
/// Escaping its scope, the pointer will be disabled automatically.
|
||||
/// Returns: a voldemorte type which can behave as same as PtrT*
|
||||
auto MapToRead(PtrT = void, T)(ref T buf) {
|
||||
return buf.Map!(PtrT, T.target, GL_READ_ONLY);
|
||||
}
|
||||
/// ditto
|
||||
auto MapToWrite(PtrT = void, T)(ref T buf) {
|
||||
return buf.Map!(PtrT, T.target, GL_WRITE_ONLY);
|
||||
}
|
||||
/// ditto
|
||||
auto MapToReadWrite(PtrT = void, T)(ref T buf) {
|
||||
return buf.Map!(PtrT, T.target, GL_READ_WRITE);
|
||||
}
|
||||
private auto Map(PtrT, GLenum target, GLenum usage)(ref BufferRef!target buf) {
|
||||
assert(!buf.empty);
|
||||
|
||||
buf.Bind();
|
||||
auto ptr = gl.MapBuffer(target, usage);
|
||||
|
||||
struct Mapper {
|
||||
public:
|
||||
@disable this(this);
|
||||
|
||||
~this() {
|
||||
gl.UnmapBuffer(target);
|
||||
}
|
||||
|
||||
static if (usage == GL_READ_ONLY) {
|
||||
@property const(PtrT*) entity() const return { return cast(PtrT*) ptr; }
|
||||
} else {
|
||||
@property inout(PtrT*) entity() inout return { return cast(PtrT*) ptr; }
|
||||
}
|
||||
alias entity this;
|
||||
}
|
||||
return Mapper();
|
||||
}
|
95
thirdparty/gl4d/src/gl4d/Framebuffer.d
vendored
Normal file
95
thirdparty/gl4d/src/gl4d/Framebuffer.d
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
/// License: MIT
|
||||
module gl4d.Framebuffer;
|
||||
|
||||
import std.conv,
|
||||
std.exception,
|
||||
std.typecons,
|
||||
std.variant;
|
||||
|
||||
import gl4d.gl,
|
||||
gl4d.math,
|
||||
gl4d.GLObject,
|
||||
gl4d.Renderbuffer,
|
||||
gl4d.Texture;
|
||||
|
||||
/// RefCounted version of OpenGL framebuffer.
|
||||
alias FramebufferRef = RefCounted!Framebuffer;
|
||||
|
||||
/// A variant type of types which can be framebuffers' attachments.
|
||||
alias FramebufferAttachment = Algebraic!(
|
||||
Texture2DRef,
|
||||
TextureRectRef,
|
||||
RenderbufferRef
|
||||
);
|
||||
|
||||
/// A wrapper type for OpenGL framebuffer.
|
||||
///
|
||||
/// Usually this is wrapped by RefCounted.
|
||||
/// When it's in default, empty() property returns true and id() property is invalid.
|
||||
struct Framebuffer {
|
||||
mixin GLObject!(
|
||||
(x, y) => gl.GenFramebuffers(x, y),
|
||||
(x) => gl.BindFramebuffer(GL_FRAMEBUFFER, x),
|
||||
(x) => gl.DeleteFramebuffers(1, x)
|
||||
);
|
||||
|
||||
public:
|
||||
~this() {
|
||||
// Forces unrefering all buffers.
|
||||
foreach (key; attachments_.keys) {
|
||||
attachments_[key] = FramebufferAttachment.init;
|
||||
}
|
||||
}
|
||||
|
||||
/// Binds this framebuffer to be read.
|
||||
void BindToRead() {
|
||||
gl.BindFramebuffer(GL_READ_FRAMEBUFFER, id);
|
||||
}
|
||||
/// Binds this framebuffer to be written.
|
||||
void BindToWrite() {
|
||||
gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, id);
|
||||
}
|
||||
|
||||
/// Validates this framebuffer.
|
||||
///
|
||||
/// This framebuffer must be bound to be written.
|
||||
void Validate() {
|
||||
const status = gl.CheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
(status == GL_FRAMEBUFFER_COMPLETE).
|
||||
enforce("The framebuffer validation failed.");
|
||||
}
|
||||
|
||||
private:
|
||||
FramebufferAttachment[GLenum] attachments_;
|
||||
}
|
||||
|
||||
/// Attaches the buffer as the attachment to the framebuffer.
|
||||
///
|
||||
/// The framebuffer must be bound to be written.
|
||||
@property void attachment(GLenum type)(
|
||||
ref FramebufferRef fb, ref RenderbufferRef buf) {
|
||||
assert(!fb.empty);
|
||||
assert(!buf.empty);
|
||||
|
||||
fb.attachments_[type] = buf;
|
||||
gl.FramebufferRenderbuffer(GL_FRAMEBUFFER, type, GL_RENDERBUFFER, buf.id);
|
||||
}
|
||||
/// ditto
|
||||
@property void attachment(GLenum type, int miplvl = 0, GLenum target)(
|
||||
ref FramebufferRef fb, ref TextureRef!target buf)
|
||||
if (target.IsSupported2DTextureTarget) {
|
||||
assert(!fb.empty);
|
||||
assert(!buf.empty);
|
||||
|
||||
fb.attachments_[type] = buf;
|
||||
gl.FramebufferTexture2D(GL_FRAMEBUFFER,
|
||||
type, target, buf.id, miplvl.to!GLint);
|
||||
}
|
||||
|
||||
/// Changes color attachments' order.
|
||||
///
|
||||
/// The framebuffer must be bound to be written.
|
||||
@property void attachmentOrder(ref FramebufferRef fb, GLenum[] attachments) {
|
||||
assert(!fb.empty);
|
||||
gl.DrawBuffers(attachments.length.to!GLsizei, attachments.ptr);
|
||||
}
|
56
thirdparty/gl4d/src/gl4d/GLObject.d
vendored
Normal file
56
thirdparty/gl4d/src/gl4d/GLObject.d
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/// License: MIT
|
||||
module gl4d.GLObject;
|
||||
|
||||
import gl4d.gl;
|
||||
|
||||
/// A template for OpenGL objects' wrapper types.
|
||||
mixin template GLObject(alias generator, alias binder, alias deleter) {
|
||||
import std.algorithm,
|
||||
std.array,
|
||||
std.typecons;
|
||||
|
||||
public:
|
||||
@disable this(this);
|
||||
|
||||
/// Creates a single object.
|
||||
static RefCounted!This Create() {
|
||||
GLuint id;
|
||||
generator(1, &id);
|
||||
return RefCounted!This(id);
|
||||
}
|
||||
/// Creates multiple objects.
|
||||
static RefCounted!This[] Create(int count) {
|
||||
assert(count > 0);
|
||||
auto id = new GLuint[count];
|
||||
generator(count, id.ptr);
|
||||
return id.map!(i => RefCounted!This(i)).array;
|
||||
}
|
||||
|
||||
~this() {
|
||||
if (!empty) deleter(&id);
|
||||
}
|
||||
|
||||
static if (is(typeof(() => binder(0)))) {
|
||||
/// Binds this object.
|
||||
void Bind() {
|
||||
assert(!empty);
|
||||
binder(id);
|
||||
}
|
||||
/// Unbinds this object
|
||||
void Unbind() {
|
||||
assert(!empty);
|
||||
binder(0);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@property bool empty() const {
|
||||
return id == 0;
|
||||
}
|
||||
|
||||
///
|
||||
const GLuint id;
|
||||
|
||||
private:
|
||||
alias This = typeof(this);
|
||||
}
|
204
thirdparty/gl4d/src/gl4d/Program.d
vendored
Normal file
204
thirdparty/gl4d/src/gl4d/Program.d
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
/// License: MIT
|
||||
module gl4d.Program;
|
||||
|
||||
import std.algorithm,
|
||||
std.array,
|
||||
std.conv,
|
||||
std.exception,
|
||||
std.string,
|
||||
std.typecons;
|
||||
|
||||
import gl4d.gl,
|
||||
gl4d.math,
|
||||
gl4d.Shader;
|
||||
|
||||
/// Whether geometry shaders are available.
|
||||
enum IsGeometryShaderAvailable = (glSupport >= GLSupport.gl40);
|
||||
|
||||
/// RefCounted version of OpenGL program.
|
||||
alias ProgramRef = RefCounted!Program;
|
||||
|
||||
/// A wrapper type for OpenGL program.
|
||||
///
|
||||
/// Usually this is wrapped by RefCounted.
|
||||
/// When it's in default, empty() property returns true and id() property is invalid.
|
||||
struct Program {
|
||||
public:
|
||||
@disable this(this);
|
||||
|
||||
///
|
||||
this(GLuint id) {
|
||||
this.id = id;
|
||||
|
||||
assert(!empty);
|
||||
(Get!GL_LINK_STATUS == GL_TRUE).enforce(log);
|
||||
}
|
||||
~this() {
|
||||
if (!empty) gl.DeleteProgram(id);
|
||||
}
|
||||
|
||||
/// Makes this program current.
|
||||
void Use() {
|
||||
assert(!empty);
|
||||
gl.UseProgram(id);
|
||||
}
|
||||
/// Makes this program incurrent.
|
||||
void Unuse() {
|
||||
assert(!empty);
|
||||
gl.UseProgram(0);
|
||||
}
|
||||
|
||||
/// Validates this program.
|
||||
///
|
||||
/// If it's failed, throws an exception with log.
|
||||
void Validate() const {
|
||||
gl.ValidateProgram(id);
|
||||
(Get!GL_VALIDATE_STATUS == GL_TRUE).enforce(log);
|
||||
}
|
||||
|
||||
/// This may takes too long time.
|
||||
@property string log() const {
|
||||
assert(!empty);
|
||||
|
||||
const len = Get!GL_INFO_LOG_LENGTH;
|
||||
|
||||
auto msg = new char[len];
|
||||
gl.GetProgramInfoLog(id, len, null, msg.ptr);
|
||||
return msg.to!string;
|
||||
}
|
||||
|
||||
///
|
||||
@property bool empty() const {
|
||||
return id == 0;
|
||||
}
|
||||
|
||||
///
|
||||
const GLuint id;
|
||||
|
||||
private:
|
||||
// Be carefully, this may take too long time.
|
||||
GLint Get(GLenum param)() const {
|
||||
GLint temp = void;
|
||||
gl.GetProgramiv(id, param, &temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
VertexShaderRef vertex_;
|
||||
|
||||
static if (IsGeometryShaderAvailable)
|
||||
GeometryShaderRef geometry_;
|
||||
|
||||
FragmentShaderRef fragment_;
|
||||
}
|
||||
|
||||
/// A linker for OpenGL program.
|
||||
struct ProgramLinker {
|
||||
public:
|
||||
///
|
||||
VertexShaderRef vertex;
|
||||
|
||||
static if (IsGeometryShaderAvailable) {
|
||||
///
|
||||
GeometryShaderRef geometry;
|
||||
///
|
||||
int geometryOutputVertices = 1024;
|
||||
///
|
||||
GLenum geometryInputType = GL_POINTS;
|
||||
///
|
||||
GLenum geometryOutputType = GL_POINTS;
|
||||
}
|
||||
|
||||
///
|
||||
FragmentShaderRef fragment;
|
||||
|
||||
///
|
||||
string[] feedbackVaryings;
|
||||
///
|
||||
bool feedbackInterleaved;
|
||||
|
||||
/// Creates new program with parameters this has.
|
||||
ProgramRef Link()
|
||||
in {
|
||||
assert(!vertex.empty);
|
||||
assert(!fragment.empty);
|
||||
}
|
||||
do {
|
||||
const id = gl.CreateProgram();
|
||||
|
||||
gl.AttachShader(id, vertex.id);
|
||||
scope(exit) vertex = vertex.init;
|
||||
|
||||
gl.AttachShader(id, fragment.id);
|
||||
scope(exit) fragment = fragment.init;
|
||||
|
||||
static if (IsGeometryShaderAvailable) if (!geometry.empty) {
|
||||
gl.AttachShader(id, geometry.id);
|
||||
scope(exit) geometry = geometry.init;
|
||||
|
||||
static if (glSupport >= GLSupport.gl40) {
|
||||
gl.ProgramParameteri(id, GL_GEOMETRY_VERTICES_OUT, geometryOutputVertices);
|
||||
|
||||
gl.ProgramParameteri(id, GL_GEOMETRY_INPUT_TYPE, geometryInputType);
|
||||
gl.ProgramParameteri(id, GL_GEOMETRY_OUTPUT_TYPE, geometryOutputType);
|
||||
}
|
||||
}
|
||||
|
||||
if (feedbackVaryings.length > 0) {
|
||||
const varys = feedbackVaryings.map!toStringz.array;
|
||||
gl.TransformFeedbackVaryings(id,
|
||||
feedbackVaryings.length.to!GLsizei, cast(char**) varys.ptr,
|
||||
feedbackInterleaved? GL_INTERLEAVED_ATTRIBS: GL_SEPARATE_ATTRIBS);
|
||||
}
|
||||
|
||||
gl.LinkProgram(id);
|
||||
return ProgramRef(id);
|
||||
}
|
||||
}
|
||||
|
||||
/// Resets uniform values with the data. (The program must be current.)
|
||||
///
|
||||
/// The program must be current.
|
||||
@property void uniform(int loc, T)(ref ProgramRef program, T data) {
|
||||
assert(!program.empty);
|
||||
|
||||
static if (is(T == int)) {
|
||||
gl.Uniform1i(loc, data);
|
||||
} else static if (is(T == vec2i)) {
|
||||
gl.Uniform2i(loc, data.x, data.y);
|
||||
} else static if (is(T == vec3i)) {
|
||||
gl.Uniform3i(loc, data.x, data.y, data.z);
|
||||
} else static if (is(T == vec4i)) {
|
||||
gl.Uniform4i(loc, data.x, data.y, data.z, data.w);
|
||||
} else static if (is(T == float)) {
|
||||
gl.Uniform1f(loc, data);
|
||||
} else static if (is(T == vec2)) {
|
||||
gl.Uniform2f(loc, data.x, data.y);
|
||||
} else static if (is(T == vec3)) {
|
||||
gl.Uniform3f(loc, data.x, data.y, data.z);
|
||||
} else static if (is(T == vec4)) {
|
||||
gl.Uniform4f(loc, data.x, data.y, data.z, data.w);
|
||||
} else static if (is(T == mat2)) {
|
||||
gl.UniformMatrix2fv(loc, 1, true, &data[0][0]);
|
||||
} else static if (is(T == mat3)) {
|
||||
gl.UniformMatrix3fv(loc, 1, true, &data[0][0]);
|
||||
} else static if (is(T == mat4)) {
|
||||
gl.UniformMatrix4fv(loc, 1, true, &data[0][0]);
|
||||
} else {
|
||||
static assert(false);
|
||||
}
|
||||
}
|
||||
// Tests for the above template.
|
||||
static assert(is(typeof((ref ProgramRef program) => program.uniform!0 = 0)));
|
||||
static assert(is(typeof((ref ProgramRef program) => program.uniform!1 = vec4())));
|
||||
static assert(is(typeof((ref ProgramRef program) => program.uniform!2 = mat4())));
|
||||
|
||||
/// Numbers uniform blocks of the names.
|
||||
void NumberUniformBlocks(string[int] names)(ref ProgramRef program) {
|
||||
assert(!program.empty);
|
||||
|
||||
GLuint ubi = void;
|
||||
static foreach (i, name; names) {
|
||||
ubi = gl.GetUniformBlockIndex(program.id, name.toStringz);
|
||||
gl.UniformBlockBinding(program.id, ubi, i.to!GLuint);
|
||||
}
|
||||
}
|
46
thirdparty/gl4d/src/gl4d/Renderbuffer.d
vendored
Normal file
46
thirdparty/gl4d/src/gl4d/Renderbuffer.d
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/// License: MIT
|
||||
module gl4d.Renderbuffer;
|
||||
|
||||
import std.conv,
|
||||
std.typecons;
|
||||
|
||||
import gl4d.gl,
|
||||
gl4d.math,
|
||||
gl4d.GLObject;
|
||||
|
||||
/// RefCounted version of OpenGL renderbuffer.
|
||||
alias RenderbufferRef = RefCounted!Renderbuffer;
|
||||
|
||||
/// A wrapper type for OpenGL renderbuffer.
|
||||
///
|
||||
/// Usually this is wrapped by RefCounted.
|
||||
/// When it's in default, empty() property returns true and id() property is invalid.
|
||||
struct Renderbuffer {
|
||||
mixin GLObject!(
|
||||
(x, y) => gl.GenRenderbuffers(x, y),
|
||||
(x) => gl.BindRenderbuffer(GL_RENDERBUFFER, x),
|
||||
(x) => gl.DeleteRenderbuffers(1, x)
|
||||
);
|
||||
}
|
||||
|
||||
/// An allocator for OpenGL renderbuffers.
|
||||
struct RenderbufferAllocator {
|
||||
public:
|
||||
///
|
||||
GLenum format;
|
||||
///
|
||||
vec2i size;
|
||||
|
||||
/// Allocates the renderbuffer's storage with parameters this has.
|
||||
///
|
||||
/// The renderbuffer will be bound automatically.
|
||||
void Allocate(ref RenderbufferRef rb)
|
||||
in {
|
||||
assert(!rb.empty);
|
||||
}
|
||||
do {
|
||||
rb.Bind();
|
||||
gl.RenderbufferStorage(GL_RENDERBUFFER,
|
||||
format, size.x.to!GLsizei, size.y.to!GLsizei);
|
||||
}
|
||||
}
|
57
thirdparty/gl4d/src/gl4d/Sampler.d
vendored
Normal file
57
thirdparty/gl4d/src/gl4d/Sampler.d
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
/// License: MIT
|
||||
module gl4d.Sampler;
|
||||
|
||||
import std.conv,
|
||||
std.typecons;
|
||||
|
||||
import gl4d.gl,
|
||||
gl4d.GLObject;
|
||||
|
||||
/// RefCounted version of Sampler.
|
||||
alias SamplerRef = RefCounted!Sampler;
|
||||
|
||||
/// A wrapper type for OpenGL sampler.
|
||||
struct Sampler {
|
||||
mixin GLObject!(
|
||||
(x, y) => gl.GenSamplers(x, y),
|
||||
void,
|
||||
(x) => gl.DeleteSamplers(1, x)
|
||||
);
|
||||
|
||||
public:
|
||||
/// Binds to the texture unit index.
|
||||
void Bind(int index) {
|
||||
assert(!empty);
|
||||
gl.BindSampler(index.to!GLuint, id);
|
||||
}
|
||||
}
|
||||
|
||||
/// A configurer for OpenGL sampler.
|
||||
struct SamplerConfigurer {
|
||||
public:
|
||||
///
|
||||
GLenum wrapS = GL_CLAMP_TO_EDGE;
|
||||
///
|
||||
GLenum wrapT = GL_CLAMP_TO_EDGE;
|
||||
///
|
||||
GLenum wrapR = GL_CLAMP_TO_EDGE;
|
||||
|
||||
///
|
||||
GLenum filterMin = GL_NEAREST;
|
||||
///
|
||||
GLenum filterMag = GL_NEAREST;
|
||||
|
||||
/// Configures the sampler with parameters this has.
|
||||
void Configure(ref SamplerRef sampler)
|
||||
in {
|
||||
assert(!sampler.empty);
|
||||
}
|
||||
do {
|
||||
gl.SamplerParameteri(sampler.id, GL_TEXTURE_WRAP_S, wrapS);
|
||||
gl.SamplerParameteri(sampler.id, GL_TEXTURE_WRAP_T, wrapT);
|
||||
gl.SamplerParameteri(sampler.id, GL_TEXTURE_WRAP_R, wrapR);
|
||||
|
||||
gl.SamplerParameteri(sampler.id, GL_TEXTURE_MIN_FILTER, filterMin);
|
||||
gl.SamplerParameteri(sampler.id, GL_TEXTURE_MAG_FILTER, filterMag);
|
||||
}
|
||||
}
|
99
thirdparty/gl4d/src/gl4d/Shader.d
vendored
Normal file
99
thirdparty/gl4d/src/gl4d/Shader.d
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
/// License: MIT
|
||||
module gl4d.Shader;
|
||||
|
||||
import std.conv,
|
||||
std.exception,
|
||||
std.string,
|
||||
std.typecons;
|
||||
|
||||
import gl4d.gl;
|
||||
|
||||
/// A wrapper type for OpenGL vertex shader.
|
||||
///
|
||||
/// Usually this is wrapped by RefCounted.
|
||||
/// When it's in default, empty() property returns true and id() property is invalid.
|
||||
struct VertexShader {
|
||||
mixin Shader!GL_VERTEX_SHADER;
|
||||
}
|
||||
/// RefCounted version of VertexShader.
|
||||
alias VertexShaderRef = RefCounted!VertexShader;
|
||||
|
||||
/// A wrapper type for OpenGL geometry shader.
|
||||
///
|
||||
/// Usually this is wrapped by RefCounted.
|
||||
/// When it's in default, empty() property returns true and id() property is invalid.
|
||||
struct GeometryShader {
|
||||
mixin Shader!GL_GEOMETRY_SHADER;
|
||||
}
|
||||
/// RefCounted version of GeometryShader.
|
||||
alias GeometryShaderRef = RefCounted!GeometryShader;
|
||||
|
||||
/// A wrapper type for OpenGL fragment shader.
|
||||
///
|
||||
/// Usually this is wrapped by RefCounted.
|
||||
/// When it's in default, empty() property returns true and id() property is invalid.
|
||||
struct FragmentShader {
|
||||
mixin Shader!GL_FRAGMENT_SHADER;
|
||||
}
|
||||
/// RefCounted version of FragmentShader.
|
||||
alias FragmentShaderRef = RefCounted!FragmentShader;
|
||||
|
||||
/// A body of shader structures which cannot be refered from other modules.
|
||||
private mixin template Shader(GLenum type) {
|
||||
public:
|
||||
@disable this(this);
|
||||
|
||||
/// Creates new shader from the source with the type.
|
||||
static RefCounted!This Compile(string src) {
|
||||
const id = gl.CreateShader(type);
|
||||
|
||||
const srcptr = src.toStringz;
|
||||
gl.ShaderSource(id, 1, &srcptr, null);
|
||||
gl.CompileShader(id);
|
||||
|
||||
return RefCounted!This(id);
|
||||
}
|
||||
|
||||
///
|
||||
this(GLuint id) {
|
||||
this.id = id;
|
||||
|
||||
assert(!empty);
|
||||
(Get!GL_COMPILE_STATUS == GL_TRUE).enforce(log);
|
||||
}
|
||||
~this() {
|
||||
if (!empty) gl.DeleteShader(id);
|
||||
}
|
||||
|
||||
/// This may takes too long time.
|
||||
@property string log() const {
|
||||
assert(!empty);
|
||||
|
||||
const len = Get!GL_INFO_LOG_LENGTH;
|
||||
if (len == 0) return null;
|
||||
|
||||
auto msg = new char[len];
|
||||
gl.GetShaderInfoLog(id, len, null, msg.ptr);
|
||||
return msg.to!string;
|
||||
}
|
||||
|
||||
///
|
||||
@property bool empty() const {
|
||||
return id == 0;
|
||||
}
|
||||
|
||||
///
|
||||
const GLuint id;
|
||||
|
||||
private:
|
||||
alias This = typeof(this);
|
||||
|
||||
// Be carefully, this may take too long time.
|
||||
GLint Get(GLenum param)() const {
|
||||
assert(!empty);
|
||||
|
||||
GLint temp = void;
|
||||
gl.GetShaderiv(id, param, &temp);
|
||||
return temp;
|
||||
}
|
||||
}
|
146
thirdparty/gl4d/src/gl4d/Texture.d
vendored
Normal file
146
thirdparty/gl4d/src/gl4d/Texture.d
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
/// License: MIT
|
||||
module gl4d.Texture;
|
||||
|
||||
import std.conv,
|
||||
std.typecons;
|
||||
|
||||
import gl4d.gl,
|
||||
gl4d.math,
|
||||
gl4d.GLObject;
|
||||
|
||||
///
|
||||
alias Texture2D = Texture!GL_TEXTURE_2D;
|
||||
/// RefCounted version of Texture2D.
|
||||
alias Texture2DRef = TextureRef!GL_TEXTURE_2D;
|
||||
///
|
||||
alias Texture2DAllocator = TextureAllocator!GL_TEXTURE_2D;
|
||||
///
|
||||
alias Texture2DOverwriter = TextureOverwriter!GL_TEXTURE_2D;
|
||||
|
||||
///
|
||||
alias TextureRect = Texture!GL_TEXTURE_RECTANGLE;
|
||||
/// RefCounted version of TextureRect.
|
||||
alias TextureRectRef = TextureRef!GL_TEXTURE_RECTANGLE;
|
||||
///
|
||||
alias TextureRectAllocator = TextureAllocator!GL_TEXTURE_RECTANGLE;
|
||||
///
|
||||
alias TextureRectOverwriter = TextureOverwriter!GL_TEXTURE_RECTANGLE;
|
||||
|
||||
/// RefCounted version of Texture.
|
||||
template TextureRef(GLenum target) {
|
||||
alias TextureRef = RefCounted!(Texture!target);
|
||||
}
|
||||
|
||||
/// A wrapper type for OpenGL texture.
|
||||
///
|
||||
/// Usually this is wrapped by RefCounted.
|
||||
/// When it's in default, empty() property returns true and id() property is invalid.
|
||||
struct Texture(GLenum target_) {
|
||||
mixin GLObject!(
|
||||
(x, y) => gl.GenTextures(x, y),
|
||||
(x) => gl.BindTexture(target_, x),
|
||||
(x) => gl.DeleteTextures(1, x)
|
||||
);
|
||||
public:
|
||||
///
|
||||
enum target = target_;
|
||||
|
||||
/// Binds this texture to the texture unit.
|
||||
///
|
||||
/// This texture will be bound.
|
||||
void BindToUnit(GLenum unit) {
|
||||
assert(!empty);
|
||||
gl.ActiveTexture(unit);
|
||||
Bind();
|
||||
}
|
||||
|
||||
/// Generates mipmaps of this texture.
|
||||
///
|
||||
/// This texture must be bound.
|
||||
void GenerateMipmap() {
|
||||
assert(!empty);
|
||||
gl.GenerateMipmap(target_);
|
||||
}
|
||||
}
|
||||
|
||||
/// An allocator for 2D textures.
|
||||
struct TextureAllocator(GLenum target)
|
||||
if (target.IsSupported2DTextureTarget()) {
|
||||
public:
|
||||
///
|
||||
int level;
|
||||
///
|
||||
GLint internalFormat;
|
||||
///
|
||||
vec2i size;
|
||||
///
|
||||
GLint border;
|
||||
///
|
||||
GLenum format;
|
||||
///
|
||||
GLenum type;
|
||||
///
|
||||
const(void)* data;
|
||||
|
||||
/// Allocates the texture with parameters this has.
|
||||
///
|
||||
/// The texture will be bound.
|
||||
void Allocate(ref TextureRef!target texture)
|
||||
in {
|
||||
assert(!texture.empty);
|
||||
|
||||
assert(level >= 0);
|
||||
assert(size.x > 0 && size.y > 0);
|
||||
assert(border == 0);
|
||||
}
|
||||
do {
|
||||
texture.Bind();
|
||||
gl.TexImage2D(target, level.to!GLint, internalFormat,
|
||||
size.x.to!GLsizei, size.y.to!GLsizei, border, format, type, data);
|
||||
}
|
||||
}
|
||||
|
||||
/// An overwriter for 2D textures.
|
||||
struct TextureOverwriter(GLenum target)
|
||||
if (target.IsSupported2DTextureTarget()) {
|
||||
public:
|
||||
///
|
||||
int level;
|
||||
///
|
||||
vec2i offset;
|
||||
///
|
||||
vec2i size;
|
||||
///
|
||||
GLenum format;
|
||||
///
|
||||
GLenum type;
|
||||
///
|
||||
const(void)* data;
|
||||
|
||||
/// Overwrites the texture with parameters this has.
|
||||
///
|
||||
/// The texture will be bound.
|
||||
void Overwrite(ref TextureRef!target texture)
|
||||
in {
|
||||
assert(!texture.empty);
|
||||
|
||||
assert(level >= 0);
|
||||
assert(offset.x >= 0 && offset.y >= 0);
|
||||
assert(size.x > 0 && size.y > 0);
|
||||
|
||||
}
|
||||
do {
|
||||
texture.Bind();
|
||||
gl.TexImage2D(target, level.to!GLint,
|
||||
offset.x.to!GLint, offset.y.to!GLint,
|
||||
size.x.to!GLsizei, size.y.to!GLsizei,
|
||||
format, type, data);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns: whether the target is supported 2d texture
|
||||
@property bool IsSupported2DTextureTarget(GLenum target) {
|
||||
return
|
||||
target == GL_TEXTURE_2D ||
|
||||
target == GL_TEXTURE_RECTANGLE;
|
||||
}
|
84
thirdparty/gl4d/src/gl4d/VertexArray.d
vendored
Normal file
84
thirdparty/gl4d/src/gl4d/VertexArray.d
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
/// License: MIT
|
||||
module gl4d.VertexArray;
|
||||
|
||||
import std.conv,
|
||||
std.typecons;
|
||||
|
||||
import gl4d.gl,
|
||||
gl4d.math,
|
||||
gl4d.Buffer,
|
||||
gl4d.GLObject;
|
||||
|
||||
/// RefCounted version of VertexArray.
|
||||
alias VertexArrayRef = RefCounted!VertexArray;
|
||||
|
||||
/// A wrapper type for OpenGL vertex array.
|
||||
///
|
||||
/// Usually this is wrapped by RefCounted.
|
||||
/// When it's in default, empty() property returns true and id() property is invalid.
|
||||
struct VertexArray {
|
||||
mixin GLObject!(
|
||||
(x, y) => gl.GenVertexArrays(x, y),
|
||||
(x) => gl.BindVertexArray(x),
|
||||
(x) => gl.DeleteVertexArrays(1, x)
|
||||
);
|
||||
|
||||
public:
|
||||
~this() {
|
||||
// Forces unrefering all buffers.
|
||||
foreach (key; attachments_.keys) {
|
||||
attachments_[key] = ArrayBufferRef.init;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ArrayBufferRef[int] attachments_;
|
||||
}
|
||||
|
||||
/// An attacher between array buffers and vertex arrays.
|
||||
struct VertexArrayAttacher {
|
||||
public:
|
||||
///
|
||||
int index;
|
||||
///
|
||||
GLenum type;
|
||||
///
|
||||
int dimension;
|
||||
///
|
||||
bool normalized;
|
||||
///
|
||||
int stride;
|
||||
///
|
||||
int offset;
|
||||
///
|
||||
int divisor;
|
||||
|
||||
/// Attaches the buffer to the vertex array with parameters this has.
|
||||
/// (The vertex array must be bound.)
|
||||
void Attach(ref VertexArrayRef va, ref ArrayBufferRef buf)
|
||||
in {
|
||||
assert(!va.empty);
|
||||
assert(!buf.empty);
|
||||
|
||||
assert(index >= 0);
|
||||
assert(0 < dimension && dimension <= 4);
|
||||
assert(stride >= 0);
|
||||
assert(offset >= 0);
|
||||
assert(divisor >= 0);
|
||||
}
|
||||
do {
|
||||
va.attachments_[index] = buf;
|
||||
|
||||
buf.Bind();
|
||||
|
||||
const i = index.to!GLuint;
|
||||
gl.EnableVertexAttribArray(i);
|
||||
|
||||
gl.VertexAttribPointer(
|
||||
i, dimension.to!GLint,
|
||||
type, normalized, stride.to!GLsizei,
|
||||
cast(GLvoid*) offset.to!ptrdiff_t);
|
||||
|
||||
gl.VertexAttribDivisor(i, divisor.to!GLuint);
|
||||
}
|
||||
}
|
65
thirdparty/gl4d/src/gl4d/gl.d
vendored
Normal file
65
thirdparty/gl4d/src/gl4d/gl.d
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
/// License: MIT
|
||||
module gl4d.gl;
|
||||
|
||||
import std.conv,
|
||||
std.exception,
|
||||
std.format;
|
||||
|
||||
public import bindbc.opengl;
|
||||
|
||||
/// This class is just for separating gl functions from the global namespace.
|
||||
abstract class gl {
|
||||
public:
|
||||
/// This library requires this version.
|
||||
enum RequiredVersion = GLSupport.gl33;
|
||||
|
||||
/// Applies current OpenGL context for gl4d features.
|
||||
///
|
||||
/// If the context version is not equal to RequiredVersion,
|
||||
/// an exception will be thrown.
|
||||
static void ApplyContext() {
|
||||
const loaded = loadOpenGL();
|
||||
(RequiredVersion == loaded).
|
||||
enforce("Loading OpenGL failed with GLSupport %s. (expected %s)".
|
||||
format(loaded, RequiredVersion));
|
||||
}
|
||||
|
||||
/// Calls OpenGL function with error handling.
|
||||
static auto opDispatch(string func,
|
||||
string file = __FILE__, size_t line = __LINE__, Args...)(Args args) {
|
||||
scope (exit) {
|
||||
auto err = glGetError();
|
||||
(err == GL_NO_ERROR).
|
||||
enforce(GetErrorString(err), file, line);
|
||||
}
|
||||
return mixin("gl"~func~"(args)");
|
||||
}
|
||||
|
||||
private:
|
||||
static string GetErrorString(GLenum err) {
|
||||
switch (err) {
|
||||
case GL_NO_ERROR:
|
||||
return "GL_NO_ERROR "~
|
||||
"(No error has been recorded."~
|
||||
" The value of this symbolic constant is guaranteed to be 0.)";
|
||||
case GL_INVALID_ENUM:
|
||||
return "GL_INVALID_ENUM "~
|
||||
"(An unacceptable value is specified for an enumerated argument."~
|
||||
" The offending command is ignored and has no other side effect than to set the error flag.)";
|
||||
case GL_INVALID_VALUE:
|
||||
return "GL_INVALID_VALUE "~
|
||||
"(A numeric argument is out of range. "~
|
||||
"The offending command is ignored and has no other side effect than to set the error flag.)";
|
||||
case GL_INVALID_OPERATION:
|
||||
return "GL_INVALID_OPERATION "~
|
||||
"(The specified operation is not allowed in the current state."~
|
||||
" The offending command is ignored and has no other side effect than to set the error flag.)";
|
||||
case GL_OUT_OF_MEMORY:
|
||||
return "GL_OUT_OF_MEMORY "~
|
||||
"(There is not enough memory left to execute the command."~
|
||||
" The state of the GL is undefined, except for the state of the error flags, after this error is recorded.";
|
||||
default:
|
||||
return err.to!string;
|
||||
}
|
||||
}
|
||||
}
|
6
thirdparty/gl4d/src/gl4d/math.d
vendored
Normal file
6
thirdparty/gl4d/src/gl4d/math.d
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/// License: MIT
|
||||
module gl4d.math;
|
||||
|
||||
public {
|
||||
import gl3n.linalg;
|
||||
}
|
17
thirdparty/gl4d/src/gl4d/package.d
vendored
Normal file
17
thirdparty/gl4d/src/gl4d/package.d
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/// License: MIT
|
||||
module gl4d;
|
||||
|
||||
public {
|
||||
import gl4d.gl,
|
||||
gl4d.math,
|
||||
gl4d.util;
|
||||
|
||||
import gl4d.Buffer,
|
||||
gl4d.Framebuffer,
|
||||
gl4d.Program,
|
||||
gl4d.Renderbuffer,
|
||||
gl4d.Sampler,
|
||||
gl4d.Shader,
|
||||
gl4d.Texture,
|
||||
gl4d.VertexArray;
|
||||
}
|
50
thirdparty/gl4d/src/gl4d/util/ModelMatrixFactory.d
vendored
Normal file
50
thirdparty/gl4d/src/gl4d/util/ModelMatrixFactory.d
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/// License: MIT
|
||||
module gl4d.util.ModelMatrixFactory;
|
||||
|
||||
import gl3n.linalg;
|
||||
|
||||
///
|
||||
struct ModelMatrixFactory(size_t dim) if (dim == 3 || dim == 4) {
|
||||
public:
|
||||
///
|
||||
alias mat = Matrix!(float, dim, dim);
|
||||
|
||||
///
|
||||
mat Create() const {
|
||||
auto m = mat.identity;
|
||||
static if (dim == 3) {
|
||||
m.scale(scale.x, scale.y, 1);
|
||||
m.rotatex(rotation.x);
|
||||
m.rotatey(rotation.y);
|
||||
m.rotatez(rotation.z);
|
||||
m.translate(translation.x, translation.y, 1);
|
||||
|
||||
} else static if (dim == 4) {
|
||||
m.scale(scale.x, scale.y, scale.z);
|
||||
m.rotatex(rotation.x);
|
||||
m.rotatey(rotation.y);
|
||||
m.rotatez(rotation.z);
|
||||
m.translate(translation.x, translation.y, translation.z);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
static if (dim == 3) {
|
||||
///
|
||||
vec2 scale = vec2(1, 1);
|
||||
///
|
||||
vec3 rotation = vec3(0, 0, 0);
|
||||
///
|
||||
vec2 translation = vec2(0, 0);
|
||||
|
||||
} else static if (dim == 4) {
|
||||
///
|
||||
vec3 scale = vec3(1, 1, 1);
|
||||
///
|
||||
vec3 rotation = vec3(0, 0, 0);
|
||||
///
|
||||
vec3 translation = vec3(0, 0, 0);
|
||||
}
|
||||
}
|
||||
static assert(__traits(compiles, ModelMatrixFactory!3));
|
||||
static assert(__traits(compiles, ModelMatrixFactory!4));
|
22
thirdparty/gl4d/src/gl4d/util/ProjectionMatrixFactory.d
vendored
Normal file
22
thirdparty/gl4d/src/gl4d/util/ProjectionMatrixFactory.d
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/// License: MIT
|
||||
module gl4d.util.ProjectionMatrixFactory;
|
||||
|
||||
import gl3n.linalg;
|
||||
|
||||
///
|
||||
struct ProjectionMatrixFactory {
|
||||
public:
|
||||
///
|
||||
mat4 Create() const {
|
||||
return mat4.perspective(aspect, 1, fov, near, far);
|
||||
}
|
||||
|
||||
///
|
||||
float aspect = 1;
|
||||
///
|
||||
float fov = 60;
|
||||
///
|
||||
float far = 100;
|
||||
///
|
||||
float near = 0.1;
|
||||
}
|
20
thirdparty/gl4d/src/gl4d/util/ViewMatrixFactory.d
vendored
Normal file
20
thirdparty/gl4d/src/gl4d/util/ViewMatrixFactory.d
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/// License: MIT
|
||||
module gl4d.util.ViewMatrixFactory;
|
||||
|
||||
import gl3n.linalg;
|
||||
|
||||
///
|
||||
struct ViewMatrixFactory {
|
||||
public:
|
||||
///
|
||||
mat4 Create() const {
|
||||
return mat4.look_at(pos, target, up);
|
||||
}
|
||||
|
||||
///
|
||||
vec3 pos = vec3(0, -1, 0);
|
||||
///
|
||||
vec3 target = vec3(0, 0, 0);
|
||||
///
|
||||
vec3 up = vec3(0, 1, 0);
|
||||
}
|
8
thirdparty/gl4d/src/gl4d/util/package.d
vendored
Normal file
8
thirdparty/gl4d/src/gl4d/util/package.d
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/// License: MIT
|
||||
module gl4d.util;
|
||||
|
||||
public {
|
||||
import gl4d.util.ModelMatrixFactory,
|
||||
gl4d.util.ProjectionMatrixFactory,
|
||||
gl4d.util.ViewMatrixFactory;
|
||||
}
|
201
thirdparty/gl4d/test.d
vendored
Normal file
201
thirdparty/gl4d/test.d
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
#!/usr/bin/env dub
|
||||
|
||||
/+ dub.json:
|
||||
{
|
||||
"name": "test",
|
||||
|
||||
"dependencies": {
|
||||
"bindbc-sdl": "~>0.11.0",
|
||||
"gl4d": {"path": "."}
|
||||
},
|
||||
"versions": ["SDL_209"]
|
||||
}
|
||||
+/
|
||||
|
||||
import std;
|
||||
import bindbc.sdl;
|
||||
import gl4d;
|
||||
|
||||
enum ShaderHeader = "#version 330 core
|
||||
#extension GL_ARB_explicit_uniform_location : enable";
|
||||
|
||||
enum VertexShaderSource = ShaderHeader~q{
|
||||
layout(location=0) in vec4 pos;
|
||||
|
||||
layout(std140) uniform uniformblock {
|
||||
float value;
|
||||
} ub;
|
||||
|
||||
out vec2 uv;
|
||||
out float feedback_value;
|
||||
|
||||
void main() {
|
||||
uv = pos.xy;
|
||||
gl_Position = pos * ub.value;
|
||||
feedback_value = length(pos.xy);
|
||||
}
|
||||
};
|
||||
enum FragmentShaderSource = ShaderHeader~q{
|
||||
in vec2 uv;
|
||||
|
||||
layout(std140) uniform uniformblock {
|
||||
float value;
|
||||
} ub;
|
||||
|
||||
layout(location = 1) uniform sampler2D tex;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
void main() {
|
||||
color = texture(tex, uv);
|
||||
}
|
||||
};
|
||||
|
||||
void Test() {
|
||||
auto tex = Texture2D.Create();
|
||||
{
|
||||
auto data = new ubyte[16*16];
|
||||
data[] = ubyte.max;
|
||||
|
||||
Texture2DAllocator allocator;
|
||||
allocator.internalFormat = GL_RGBA8;
|
||||
allocator.size = vec2i(16, 16);
|
||||
allocator.format = GL_RED;
|
||||
allocator.type = GL_UNSIGNED_BYTE;
|
||||
allocator.data = data.ptr;
|
||||
allocator.Allocate(tex);
|
||||
}
|
||||
|
||||
auto sampler = Sampler.Create();
|
||||
{
|
||||
SamplerConfigurer configurer;
|
||||
configurer.filterMin = GL_NEAREST;
|
||||
configurer.filterMag = GL_NEAREST;
|
||||
configurer.Configure(sampler);
|
||||
}
|
||||
|
||||
auto buf = ArrayBuffer.Create();
|
||||
{
|
||||
ArrayBufferAllocator allocator;
|
||||
allocator.size = float.sizeof*4*3;
|
||||
allocator.data = null;
|
||||
allocator.usage = GL_STATIC_DRAW;
|
||||
allocator.Allocate(buf);
|
||||
|
||||
auto ptr = buf.MapToWrite!float();
|
||||
ptr[0] = 0;
|
||||
ptr[1] = 0;
|
||||
ptr[2] = 0;
|
||||
ptr[3] = 1;
|
||||
|
||||
ptr[4] = 0.5;
|
||||
ptr[5] = 0.5;
|
||||
ptr[6] = 0;
|
||||
ptr[7] = 1;
|
||||
|
||||
ptr[8] = 0.5;
|
||||
ptr[9] = 0;
|
||||
ptr[10] = 0;
|
||||
ptr[11] = 1;
|
||||
}
|
||||
|
||||
auto buf_tf = ArrayBuffer.Create();
|
||||
{
|
||||
ArrayBufferAllocator allocator;
|
||||
allocator.size = float.sizeof * 3;
|
||||
allocator.data = null;
|
||||
allocator.usage = GL_STREAM_COPY;
|
||||
allocator.Allocate(buf_tf);
|
||||
}
|
||||
|
||||
auto ub = UniformBuffer.Create();
|
||||
{
|
||||
const data = 1.5f;
|
||||
UniformBufferAllocator allocator;
|
||||
allocator.size = float.sizeof;
|
||||
allocator.data = &data;
|
||||
allocator.usage = GL_STATIC_DRAW;
|
||||
allocator.Allocate(ub);
|
||||
}
|
||||
|
||||
ProgramRef program;
|
||||
{
|
||||
ProgramLinker linker;
|
||||
linker.vertex = VertexShader.Compile(VertexShaderSource);
|
||||
linker.fragment = FragmentShader.Compile(FragmentShaderSource);
|
||||
linker.feedbackVaryings = ["feedback_value"];
|
||||
linker.feedbackInterleaved = true;
|
||||
program = linker.Link();
|
||||
program.NumberUniformBlocks!(["uniformblock"]);
|
||||
|
||||
program.Use();
|
||||
program.uniform!1 = 0;
|
||||
}
|
||||
|
||||
auto va = VertexArray.Create();
|
||||
{
|
||||
va.Bind();
|
||||
VertexArrayAttacher attacher;
|
||||
attacher.index = 0;
|
||||
attacher.type = GL_FLOAT;
|
||||
attacher.dimension = 4;
|
||||
attacher.Attach(va, buf);
|
||||
}
|
||||
|
||||
auto rb = Renderbuffer.Create();
|
||||
{
|
||||
RenderbufferAllocator allocator;
|
||||
allocator.format = GL_RGB8;
|
||||
allocator.size = vec2i(32, 32);
|
||||
allocator.Allocate(rb);
|
||||
}
|
||||
|
||||
auto fb = Framebuffer.Create();
|
||||
{
|
||||
fb.Bind();
|
||||
fb.attachment!GL_COLOR_ATTACHMENT0 = rb;
|
||||
fb.attachmentOrder = [GL_COLOR_ATTACHMENT0];
|
||||
fb.Validate();
|
||||
fb.Unbind();
|
||||
}
|
||||
|
||||
buf_tf.BindForTransformFeedback(0);
|
||||
ub.BindForUniformBlock(0);
|
||||
tex.BindToUnit(GL_TEXTURE0);
|
||||
sampler.Bind(0);
|
||||
|
||||
gl.BeginTransformFeedback(GL_POINTS);
|
||||
gl.PointSize(5);
|
||||
gl.DrawArrays(GL_POINTS, 0, 3);
|
||||
gl.EndTransformFeedback();
|
||||
|
||||
{
|
||||
auto ptr = buf_tf.MapToRead!float();
|
||||
static foreach (i; 0..3) ptr[i].writeln;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
(loadSDL() == sdlSupport).
|
||||
enforce("SDL library loading failed.");
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
scope(exit) SDL_Quit();
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
|
||||
auto win = SDL_CreateWindow("gl4d testing", 0, 0, 100, 100, SDL_WINDOW_OPENGL).
|
||||
enforce("Failed creating OpenGL window.");
|
||||
scope(exit) SDL_DestroyWindow(win);
|
||||
|
||||
auto context = SDL_GL_CreateContext(win);
|
||||
SDL_GL_MakeCurrent(win, context);
|
||||
gl.ApplyContext();
|
||||
|
||||
Test();
|
||||
|
||||
SDL_GL_SwapWindow(win);
|
||||
SDL_Delay(3000);
|
||||
}
|
Reference in New Issue
Block a user