summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsanine-a <sanine.not@pm.me>2020-10-31 22:43:41 -0500
committersanine-a <sanine.not@pm.me>2020-10-31 22:43:41 -0500
commit42d42c9ba3b741d167eaa2196c686962559686f1 (patch)
tree46f9d9c51d1d4fe1ccbacf1d1f73c066e93dfc32
parentad75604ec79d70d328595f114e65bac80db9999f (diff)
add basic framebuffer operations
-rw-r--r--demo/ScreenQuad.lua47
-rw-r--r--demo/main.lua37
-rw-r--r--src/honey.c63
-rw-r--r--src/honey.h8
-rw-r--r--src/primitives/primitives.c2
-rw-r--r--src/texture/texture.c89
-rw-r--r--src/texture/texture.h21
7 files changed, 244 insertions, 23 deletions
diff --git a/demo/ScreenQuad.lua b/demo/ScreenQuad.lua
new file mode 100644
index 0000000..938674c
--- /dev/null
+++ b/demo/ScreenQuad.lua
@@ -0,0 +1,47 @@
+local ScreenQuad = {}
+
+ScreenQuad.quad = honey.primitives.plane(2,2)
+
+local vertexShader = [[
+#version 330 core
+
+layout(location = 0) in vec3 position;
+layout(location = 1) in vec3 normal;
+layout(location = 2) in vec2 uv;
+
+out vec2 UV;
+
+void main()
+{
+ gl_Position = vec4(position.xy, 0, 1) - vec4(1,1,0,0);
+ UV = uv;
+} ]]
+
+local fragmentShader = [[
+#version 330 core
+
+in vec2 UV;
+
+uniform sampler2D tex;
+
+out vec4 color;
+
+void main()
+{
+ color = vec4(texture(tex, UV));
+} ]]
+
+ScreenQuad.shader = honey.shader.new(vertexShader, fragmentShader)
+
+ScreenQuad.texture = honey.texture.new()
+honey.texture.create(ScreenQuad.texture, 'rgba', 640, 480);
+--honey.texture.load(ScreenQuad.texture, 'checkerboard.png', false)
+
+ScreenQuad.fb = honey.texture.new_framebuffer(ScreenQuad.texture, nil, 640, 480)
+
+ScreenQuad.draw = function(self)
+ honey.texture.use(self.texture, 0)
+ honey.mesh.draw(self.quad, self.shader)
+end
+
+return ScreenQuad
diff --git a/demo/main.lua b/demo/main.lua
index 3c32b6f..5474609 100644
--- a/demo/main.lua
+++ b/demo/main.lua
@@ -1,6 +1,7 @@
local Vector = require('Vector')
local Matrix = require('Matrix')
local FPSCamera = require('FPSCamera')
+local ScreenQuad = require('ScreenQuad')
FPSCamera.movement_speed = 5
local model = Matrix.Mat4.eye()
@@ -10,9 +11,11 @@ print(model)
honey.input.key.bind(honey.input.key.escape, honey.exit)
+local buffer = false
+honey.input.key.bind(honey.input.key.f, function(action) if action == 1 then buffer = not buffer end end)
+
local tex = honey.texture.new()
honey.texture.load(tex, 'checkerboard.png', false)
-honey.texture.use(tex, 0)
local vertex_shader = [[
#version 330 core
@@ -49,12 +52,13 @@ uniform sampler2D tex;
out vec4 color;
void main() {
- vec2 texture_coords = UV + (time * vec2(100,100));
- color = vec4(texture(tex, texture_coords).xyz, 1);
+ //vec2 texture_coords = UV + (time * vec2(100,100));
+ color = vec4(texture(tex, UV).xyz, 1);
} ]]
local shader = honey.shader.new(vertex_shader, fragment_shader)
-local plane = honey.mesh.load('Suzanne.obj')[1]
+local suzanne = honey.mesh.load('Suzanne.obj')[1]
+local plane = honey.primitives.plane(4,4)
local color1 = Vector.Vec4.new{1,0,0,1}
local color2 = Vector.Vec4.new{0,0,1,1}
@@ -73,11 +77,32 @@ function honey.update(dt)
end
end
-function honey.draw()
- total_frames = total_frames + 1
+function draw_suzanne()
+ honey.texture.use(tex, 0)
honey.shader.set_mat4(shader, 'model', model.array)
honey.shader.set_mat4(shader, 'view', FPSCamera.view.array)
honey.shader.set_mat4(shader, 'projection', FPSCamera.projection.array)
honey.shader.set_float(shader, 'time', total_time)
+ honey.mesh.draw(suzanne, shader)
honey.mesh.draw(plane, shader)
end
+
+function honey.draw()
+ total_frames = total_frames + 1
+
+ if buffer then
+ honey.set_framebuffer(ScreenQuad.fb)
+ honey.enable_depth_test(true)
+ honey.clear_color(Vector.Vec4.new().array, true, true, false)
+ draw_suzanne()
+
+ honey.set_framebuffer(0)
+ honey.enable_depth_test(true)
+ honey.clear_color(Vector.Vec4.new{0,0,1,1}.array, true, true, false)
+ ScreenQuad:draw()
+ else
+ honey.clear_color(Vector.Vec4.new{1,1,0,1}.array, true, true, false)
+ honey.enable_depth_test(true)
+ draw_suzanne()
+ end
+end
diff --git a/src/honey.c b/src/honey.c
index 1328a5f..ce1a38c 100644
--- a/src/honey.c
+++ b/src/honey.c
@@ -54,6 +54,48 @@ bool honey_parse_options(honey_options* options, int argc, char** argv)
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+static int honey_lua_clear_color(lua_State* L)
+{
+ float* color_array;
+ bool color, depth, stencil;
+ honey_lua_parse_arguments(L, 4,
+ HONEY_USERDATA, &color_array,
+ HONEY_BOOLEAN, &color,
+ HONEY_BOOLEAN, &depth,
+ HONEY_BOOLEAN, &stencil);
+ float r = color_array[0];
+ float g = color_array[1];
+ float b = color_array[2];
+ float a = color_array[3];
+
+ int clear_flags = 0;
+ if (color)
+ clear_flags = clear_flags | GL_COLOR_BUFFER_BIT;
+ if (depth)
+ clear_flags = clear_flags | GL_DEPTH_BUFFER_BIT;
+ if (stencil)
+ clear_flags = clear_flags | GL_STENCIL_BUFFER_BIT;
+
+ glClearColor(r, g, b, a);
+ glClear(clear_flags);
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_lua_enable_depth_test(lua_State* L)
+{
+ bool enable;
+ honey_lua_parse_arguments(L, 1, HONEY_BOOLEAN, &enable);
+ if (enable)
+ glEnable(GL_DEPTH_TEST);
+ else
+ glDisable(GL_DEPTH_TEST);
+ return 0;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
bool honey_setup(lua_State** L)
{
@@ -88,6 +130,15 @@ bool honey_setup(lua_State** L)
lua_pushcfunction(*L, honey_exit);
lua_setfield(*L, -2, "exit");
+ lua_pushcfunction(*L, honey_set_framebuffer);
+ lua_setfield(*L, -2, "set_framebuffer");
+
+ lua_pushcfunction(*L, honey_lua_clear_color);
+ lua_setfield(*L, -2, "clear_color");
+
+ lua_pushcfunction(*L, honey_lua_enable_depth_test);
+ lua_setfield(*L, -2, "enable_depth_test");
+
lua_setglobal(*L, "honey");
return true;
@@ -145,8 +196,6 @@ bool honey_run(lua_State* L, honey_options opts) {
if (drawTime > 0.016) {
drawTime -= 0.016;
- glClearColor(0,0,0,1);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (draw_callback != LUA_NOREF) {
lua_rawgeti(L, LUA_REGISTRYINDEX, draw_callback);
@@ -185,3 +234,13 @@ int honey_get_callback(lua_State* L, char* callback)
return ref;
}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+int honey_set_framebuffer(lua_State* L)
+{
+ int framebuffer;
+ honey_lua_parse_arguments(L, 1, HONEY_INTEGER, &framebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+ return 0;
+}
diff --git a/src/honey.h b/src/honey.h
index 8231b70..5a2e6c2 100644
--- a/src/honey.h
+++ b/src/honey.h
@@ -68,4 +68,12 @@ bool honey_run(lua_State* L, honey_options opts);
*/
int honey_get_callback(lua_State* L, char* callback);
+/** @brief Set the current render target.
+ *
+ * @param[in] framebuffer The framebuffer to target, or 0 to target the window's framebuffer.
+ *
+ * @returns Nothing.
+ */
+int honey_set_framebuffer(lua_State* L);
+
#endif
diff --git a/src/primitives/primitives.c b/src/primitives/primitives.c
index 8293d4d..d499248 100644
--- a/src/primitives/primitives.c
+++ b/src/primitives/primitives.c
@@ -60,7 +60,7 @@ honey_result honey_mesh_new_textured_plane(honey_mesh* mesh,
unsigned int indices[] = {
0, 1, 2,
- 1, 2, 3 };
+ 3, 2, 1 };
unsigned int attrib_sizes[] = { 3, 3, 2 };
diff --git a/src/texture/texture.c b/src/texture/texture.c
index 6df19a7..9ddf441 100644
--- a/src/texture/texture.c
+++ b/src/texture/texture.c
@@ -6,6 +6,37 @@ static int honey_lua_texture_new(lua_State* L)
return 1;
}
+static int honey_lua_texture_create(lua_State* L)
+{
+ honey_texture* texture;
+ int width, height;
+ char* type;
+ honey_lua_parse_arguments(L, 4,
+ HONEY_USERDATA, &texture,
+ HONEY_STRING, &type,
+ HONEY_INTEGER, &width,
+ HONEY_INTEGER, &height);
+
+ if (strcmp(type, "greyscale") == 0)
+ honey_texture_new_greyscale(texture, width, height, NULL);
+ else if (strcmp(type, "rgb") == 0)
+ honey_texture_new_rgb(texture, width, height, NULL);
+ else if (strcmp(type, "rgba") == 0)
+ honey_texture_new_rgba(texture, width, height, NULL);
+ else if (strcmp(type, "depth") == 0)
+ honey_texture_new_depth(texture, width, height, NULL);
+ else {
+ char* error;
+ honey_format_string(&error,
+ "unknown texture type '%s'",
+ type);
+ lua_pushstring(L, error);
+ free(error);
+ lua_error(L);
+ }
+ return 0;
+}
+
static int honey_lua_texture_load(lua_State* L)
{
honey_texture* texture;
@@ -38,15 +69,43 @@ static int honey_lua_texture_use(lua_State* L)
return 0;
}
+static int honey_lua_framebuffer_new(lua_State* L)
+{
+ honey_texture* draw, *depth;
+ if (lua_isuserdata(L, 1))
+ draw = lua_touserdata(L, 1);
+ else
+ draw = NULL;
+
+ if (lua_isuserdata(L, 2))
+ depth = lua_touserdata(L, 2);
+ else
+ depth = NULL;
+
+ int width, height;
+ honey_lua_parse_arguments(L, 4, HONEY_ANY, HONEY_ANY,
+ HONEY_INTEGER, &width,
+ HONEY_INTEGER, &height);
+
+ unsigned int framebuffer;
+ honey_texture_framebuffer_object_new(&framebuffer,
+ draw, depth,
+ width, height);
+ lua_pushinteger(L, framebuffer);
+ return 1;
+}
+
void honey_setup_texture(lua_State* L)
{
honey_lua_element texture_elements[] = {
{ "new", HONEY_FUNCTION, { .function = honey_lua_texture_new } },
+ { "new_framebuffer", HONEY_FUNCTION, { .function = honey_lua_framebuffer_new } },
+ { "create", HONEY_FUNCTION, { .function = honey_lua_texture_create } },
{ "load", HONEY_FUNCTION, { .function = honey_lua_texture_load } },
{ "use", HONEY_FUNCTION, { .function = honey_lua_texture_use } },
};
- honey_lua_create_table(L, texture_elements, 3);
+ honey_lua_create_table(L, texture_elements, 5);
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
@@ -182,10 +241,26 @@ void honey_texture_use(honey_texture texture, int texture_unit) {
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-//honey_result honey_texture_framebuffer_object_new(unsigned int* destination,
-// int width, int height)
-//{
-// glGenFramebuffers(1, destination);
-// glBindFramebuffer(GL_FRAMEBUFFER, *destination);
+void honey_texture_framebuffer_object_new(unsigned int* destination,
+ honey_texture* draw,
+ honey_texture* depth,
+ int width, int height)
+{
+ glGenFramebuffers(1, destination);
+ glBindFramebuffer(GL_FRAMEBUFFER, *destination);
+
+ if (draw != NULL)
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, draw->id, 0);
+ else {
+ glDrawBuffer(GL_NONE);
+ glReadBuffer(GL_NONE);
+ }
-
+ if (depth != NULL)
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth->id, 0);
+
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ printf("framebuffer is not complete!\n");
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+}
diff --git a/src/texture/texture.h b/src/texture/texture.h
index 785fef0..9dc0308 100644
--- a/src/texture/texture.h
+++ b/src/texture/texture.h
@@ -37,7 +37,7 @@ void honey_setup_texture(lua_State* L);
* @param[in] height The height in pixels of the texture to create.
* @param[in] data The data to populate the texture with, or NULL to leave it unpopulated.
*
- * @returns HONEY_OK on success, and appropriate error on failure.
+ * @returns Nothing.
*/
void honey_texture_new_greyscale(honey_texture* texture,
int width, int height,
@@ -50,7 +50,7 @@ void honey_texture_new_greyscale(honey_texture* texture,
* @param[in] height The height in pixels of the texture to create.
* @param[in] data The data to populate the texture with, or NULL to leave it unpopulated.
*
- * @returns HONEY_OK on success, and appropriate error on failure.
+ * @returns Nothing.
*/
void honey_texture_new_rgb(honey_texture* texture,
int width, int height,
@@ -63,7 +63,7 @@ void honey_texture_new_rgb(honey_texture* texture,
* @param[in] height The height in pixels of the texture to create.
* @param[in] data The data to populate the texture with, or NULL to leave it unpopulated.
*
- * @returns HONEY_OK on success, and appropriate error on failure.
+ * @returns Nothing.
*/
void honey_texture_new_rgba(honey_texture* texture,
int width, int height,
@@ -76,7 +76,7 @@ void honey_texture_new_rgba(honey_texture* texture,
* @param[in] height The height in pixels of the texture to create.
* @param[in] data The data to populate the texture with, or NULL to leave it unpopulated.
*
- * @returns HONEY_OK on success, and appropriate error on failure.
+ * @returns Nothing.
*/
void honey_texture_new_depth(honey_texture* texture,
int width, int height,
@@ -102,13 +102,20 @@ void honey_texture_use(honey_texture texture, int texture_unit);
/** @brief Create a framebuffer object.
*
+ * You must specify at least one of draw and depth; otherwise, the framebuffer will
+ * be incomplete and fail.
+ *
* @param[out] destination Pointer to store the resulting OpenGL handle in.
+ * @param[in] draw Pointer to a texture to draw to.
+ * @param[in] depth Pointer to a depth texture.
* @param[in] width The width in pixels of the FBO.
* @param[in] height The height in pixels of the FBO.
*
- * @returns HONEY_OK on success; appropriate error otherwise.
+ * @returns Nothing.
*/
-honey_result honey_texture_framebuffer_object_new(unsigned int* destination,
- int width, int height);
+void honey_texture_framebuffer_object_new(unsigned int* destination,
+ honey_texture* draw,
+ honey_texture* depth,
+ int width, int height);
#endif