draw flames on torches
This commit is contained in:
parent
c299825859
commit
ce7c4c4cc6
1
Makefile
1
Makefile
@ -47,6 +47,7 @@ OBJS = \
|
|||||||
src/collada/animate.o \
|
src/collada/animate.o \
|
||||||
src/lua_api.o \
|
src/lua_api.o \
|
||||||
src/pixel_line_art.o \
|
src/pixel_line_art.o \
|
||||||
|
src/flame.o \
|
||||||
data/scenes/ship20/ship20.o \
|
data/scenes/ship20/ship20.o \
|
||||||
data/scenes/noodle/noodle.o \
|
data/scenes/noodle/noodle.o \
|
||||||
data/scenes/shadow_test/shadow_test.o \
|
data/scenes/shadow_test/shadow_test.o \
|
||||||
|
|||||||
7
include/flame.h
Normal file
7
include/flame.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace flame {
|
||||||
|
void load_program();
|
||||||
|
void load_texture();
|
||||||
|
void draw(unsigned int light_uniform_buffer, int light_count);
|
||||||
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "directxmath/directxmath.h"
|
||||||
|
|
||||||
namespace view {
|
namespace view {
|
||||||
struct view_state {
|
struct view_state {
|
||||||
// positions
|
// positions
|
||||||
|
|||||||
BIN
minecraft/flame.data
Normal file
BIN
minecraft/flame.data
Normal file
Binary file not shown.
@ -113,8 +113,8 @@ def pack_instance_data(position, block_id, block_data, texture_id):
|
|||||||
block_id, block_data, texture_id, special)
|
block_id, block_data, texture_id, special)
|
||||||
return packed
|
return packed
|
||||||
|
|
||||||
def pack_light_data(position, block_id):
|
def pack_light_data(position, block_id, block_data):
|
||||||
packed = struct.pack("<ffff", position[0], position[1], position[2], block_id)
|
packed = struct.pack("<ffff", position[0], position[1], position[2], block_data)
|
||||||
return packed
|
return packed
|
||||||
|
|
||||||
def build_block_instances(blocks):
|
def build_block_instances(blocks):
|
||||||
@ -174,7 +174,7 @@ def build_block_instances(blocks):
|
|||||||
|
|
||||||
with open(f"{data_path}.lights.vtx", "wb") as f:
|
with open(f"{data_path}.lights.vtx", "wb") as f:
|
||||||
for position, block_id, block_data in light_sources:
|
for position, block_id, block_data in light_sources:
|
||||||
packed = pack_light_data(position, block_id)
|
packed = pack_light_data(position, block_id, block_data)
|
||||||
f.write(packed)
|
f.write(packed)
|
||||||
|
|
||||||
def level_table_from_path(level_table, path):
|
def level_table_from_path(level_table, path):
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
28
shader/flame.frag
Normal file
28
shader/flame.frag
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#version 430 core
|
||||||
|
|
||||||
|
in vec4 PixelTexture;
|
||||||
|
|
||||||
|
layout (location = 0, binding = 0) uniform sampler2D FlameSampler;
|
||||||
|
layout (location = 1) uniform int Frame;
|
||||||
|
|
||||||
|
layout (location = 0) out vec3 Position;
|
||||||
|
layout (location = 1) out vec4 Normal;
|
||||||
|
layout (location = 2) out vec3 Color;
|
||||||
|
layout (location = 3) out vec4 Block;
|
||||||
|
|
||||||
|
const float frames = 1.0 / 4.0;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 coord = vec2(PixelTexture.x, 1.0 - PixelTexture.y) * vec2(1, frames) + vec2(0, frames * Frame);
|
||||||
|
vec4 texture_color = texture(FlameSampler, coord);
|
||||||
|
if (texture_color.w == 0) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Position = vec3(0, 0, 0);
|
||||||
|
Normal = vec4(0, 0, 0, 0);
|
||||||
|
Color = vec3(texture_color.xyz);
|
||||||
|
Block = vec4(-1, -1, -1, -1);
|
||||||
|
}
|
||||||
42
shader/flame.vert
Normal file
42
shader/flame.vert
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#version 430 core
|
||||||
|
|
||||||
|
layout (location = 2) uniform mat4 Transform;
|
||||||
|
layout (location = 3) uniform vec3 Eye;
|
||||||
|
|
||||||
|
const vec2 vtx[4] = vec2[](vec2(-1.0, 1.0), // tl
|
||||||
|
vec2( 1.0, 1.0), // tr
|
||||||
|
vec2( 1.0, -1.0), // br
|
||||||
|
vec2(-1.0, -1.0)); // bl
|
||||||
|
|
||||||
|
out vec4 PixelTexture;
|
||||||
|
|
||||||
|
const vec3 up = vec3(0, 0, 1);
|
||||||
|
|
||||||
|
layout (std140, binding = 0) uniform Lights
|
||||||
|
{
|
||||||
|
vec4 light[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 vertex = vtx[gl_VertexID];
|
||||||
|
|
||||||
|
PixelTexture = vec4(vertex * 0.5 + 0.5, 0, 0);
|
||||||
|
|
||||||
|
vec4 light_instance = light[gl_InstanceID];
|
||||||
|
bool is_candle = light_instance.w == 5;
|
||||||
|
float z_offset = is_candle ? 0.17 : 0.5;
|
||||||
|
float y_offset = float(light_instance.w == 4) - float(light_instance.w == 3);
|
||||||
|
float x_offset = float(light_instance.w == 2) - float(light_instance.w == 1);
|
||||||
|
|
||||||
|
float size = is_candle ? 0.1 : 0.25;
|
||||||
|
|
||||||
|
vec3 global_position = light_instance.xzy + vec3(x_offset * 0.2, y_offset * 0.2, z_offset);
|
||||||
|
vec3 direction = global_position - Eye;
|
||||||
|
vec3 normal = normalize(vec3(direction.x, direction.y, 0));
|
||||||
|
vec3 right = normalize(cross(normal, up));
|
||||||
|
|
||||||
|
vec3 position = global_position + (vertex.x * right + vertex.y * up) * size;
|
||||||
|
|
||||||
|
gl_Position = Transform * vec4(position, 1);
|
||||||
|
}
|
||||||
@ -41,5 +41,8 @@ void main()
|
|||||||
//vec3 light_direction = normalize(Eye.xyz - position.xyz);
|
//vec3 light_direction = normalize(Eye.xyz - position.xyz);
|
||||||
//float diffuse = max(dot(normal.xyz, light_direction), 0.0);
|
//float diffuse = max(dot(normal.xyz, light_direction), 0.0);
|
||||||
|
|
||||||
|
if (normal == vec4(0, 0, 0, 0))
|
||||||
|
out_color = color.xyz;
|
||||||
|
|
||||||
Color = vec4(out_color, 1.0);
|
Color = vec4(out_color, 1.0);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,7 +46,7 @@ void main()
|
|||||||
|
|
||||||
vs_out.Position = position;
|
vs_out.Position = position;
|
||||||
vs_out.BlockPosition = BlockPosition;
|
vs_out.BlockPosition = BlockPosition;
|
||||||
vs_out.Normal = Normal;
|
vs_out.Normal = orientation(Normal);
|
||||||
vs_out.Texture = Texture;
|
vs_out.Texture = Texture;
|
||||||
vs_out.BlockID = BlockID;
|
vs_out.BlockID = BlockID;
|
||||||
vs_out.Data = Data;
|
vs_out.Data = Data;
|
||||||
|
|||||||
106
src/flame.cpp
Normal file
106
src/flame.cpp
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "glad/gl.h"
|
||||||
|
|
||||||
|
#include "file.h"
|
||||||
|
#include "opengl.h"
|
||||||
|
|
||||||
|
#include "flame.h"
|
||||||
|
#include "view.h"
|
||||||
|
|
||||||
|
extern unsigned int quad_index_buffer;
|
||||||
|
extern unsigned int empty_vertex_array_object;
|
||||||
|
|
||||||
|
namespace flame {
|
||||||
|
static unsigned int program;
|
||||||
|
static unsigned int flame_texture;
|
||||||
|
static unsigned int vertex_array_object;
|
||||||
|
|
||||||
|
const int per_instance_size = 4 * (sizeof (float));
|
||||||
|
|
||||||
|
struct layout {
|
||||||
|
struct {
|
||||||
|
unsigned int flame_sampler;
|
||||||
|
unsigned int frame;
|
||||||
|
unsigned int transform;
|
||||||
|
unsigned int eye;
|
||||||
|
} uniform;
|
||||||
|
struct {
|
||||||
|
unsigned int lights;
|
||||||
|
} binding;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout layout = {
|
||||||
|
.uniform = {
|
||||||
|
.flame_sampler = 0,
|
||||||
|
.frame = 1,
|
||||||
|
.transform = 2,
|
||||||
|
.eye = 3,
|
||||||
|
},
|
||||||
|
.binding = {
|
||||||
|
.lights = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
void load_program()
|
||||||
|
{
|
||||||
|
program = compile_from_files("shader/flame.vert",
|
||||||
|
nullptr,
|
||||||
|
"shader/flame.frag");
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_texture()
|
||||||
|
{
|
||||||
|
unsigned int texture;
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
int texture_data_size;
|
||||||
|
void * texture_data = read_file("minecraft/flame.data", &texture_data_size);
|
||||||
|
assert(texture_data != nullptr);
|
||||||
|
|
||||||
|
int width = 16;
|
||||||
|
int height = 80;
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
|
||||||
|
|
||||||
|
free(texture_data);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
flame_texture = texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int frame = 0;
|
||||||
|
|
||||||
|
void draw(unsigned int light_uniform_buffer, int light_count)
|
||||||
|
{
|
||||||
|
glUseProgram(program);
|
||||||
|
|
||||||
|
glBlendFunc(GL_ONE, GL_ZERO);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthFunc(GL_GREATER);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, flame_texture);
|
||||||
|
glUniform1i(layout.uniform.frame, (frame / 20) % 4);
|
||||||
|
frame++;
|
||||||
|
|
||||||
|
glUniformMatrix4fv(layout.uniform.transform, 1, false, (float *)&view::state.float_transform);
|
||||||
|
XMFLOAT3 eye;
|
||||||
|
XMStoreFloat3(&eye, view::state.eye);
|
||||||
|
glUniform3fv(layout.uniform.eye, 1, (float *)&eye);
|
||||||
|
|
||||||
|
glBindBufferBase(GL_UNIFORM_BUFFER, layout.binding.lights, light_uniform_buffer);
|
||||||
|
|
||||||
|
glBindVertexArray(empty_vertex_array_object);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_index_buffer);
|
||||||
|
|
||||||
|
glDrawElementsInstanced(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, (void *)0, light_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -101,9 +101,9 @@ namespace hud {
|
|||||||
y += ter_best.desc->glyph_height;
|
y += ter_best.desc->glyph_height;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
y = draw_vector(ter_best, buf, y, "eye", view::state.eye);
|
y = draw_vector(ter_best, buf, y, "eye", XMVectorSetW(view::state.eye, 0));
|
||||||
y = draw_vector(ter_best, buf, y, "at", view::state.at);
|
y = draw_vector(ter_best, buf, y, "at", XMVectorSetW(view::state.at, 0));
|
||||||
y = draw_vector(ter_best, buf, y, "forward", view::state.forward);
|
y = draw_vector(ter_best, buf, y, "forward", XMVectorSetW(view::state.forward, 0));
|
||||||
|
|
||||||
labeled_value<float>(buf, "pitch: ", "%.4f", view::state.pitch);
|
labeled_value<float>(buf, "pitch: ", "%.4f", view::state.pitch);
|
||||||
font::draw_string(ter_best, buf, 10, y);
|
font::draw_string(ter_best, buf, 10, y);
|
||||||
|
|||||||
14
src/test.cpp
14
src/test.cpp
@ -25,6 +25,7 @@
|
|||||||
#include "collada/types.h"
|
#include "collada/types.h"
|
||||||
#include "collada/instance_types.h"
|
#include "collada/instance_types.h"
|
||||||
#include "pixel_line_art.h"
|
#include "pixel_line_art.h"
|
||||||
|
#include "flame.h"
|
||||||
|
|
||||||
#include "world/entry_table.h"
|
#include "world/entry_table.h"
|
||||||
#include "world/world.h"
|
#include "world/world.h"
|
||||||
@ -195,6 +196,13 @@ void load(const char * source_path)
|
|||||||
|
|
||||||
//node_at = scene_state.find_node_by_name("Camera001.Target");
|
//node_at = scene_state.find_node_by_name("Camera001.Target");
|
||||||
//assert(node_at != nullptr);
|
//assert(node_at != nullptr);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// flame
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
flame::load_program();
|
||||||
|
flame::load_texture();
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_keyboard(int up, int down, int left, int right,
|
void update_keyboard(int up, int down, int left, int right,
|
||||||
@ -418,13 +426,15 @@ void draw()
|
|||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
minecraft::draw();
|
minecraft::draw();
|
||||||
//draw_line();
|
|
||||||
non_block::draw();
|
non_block::draw();
|
||||||
|
|
||||||
|
flame::draw(minecraft::current_world->light_uniform_buffer,
|
||||||
|
minecraft::current_world->light_count);
|
||||||
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
|
||||||
lighting::draw(minecraft::current_world->light_uniform_buffer,
|
lighting::draw(minecraft::current_world->light_uniform_buffer,
|
||||||
minecraft::current_world->light_count);
|
minecraft::current_world->light_count);
|
||||||
//draw_quad();
|
//draw_quad();
|
||||||
|
|||||||
@ -97,14 +97,14 @@ namespace view {
|
|||||||
state.up = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f);
|
state.up = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
state.fov = 1.5;
|
state.fov = 1.5;
|
||||||
state.pitch = -0.7;
|
state.pitch = -0.5520;
|
||||||
|
|
||||||
state.forward = XMVector3Normalize(XMVectorSet(-0.64, 0.77, 0, 0));
|
state.forward = XMVector3Normalize(XMVectorSet(0.66, -0.75, 0, 0));
|
||||||
state.normal = get_normal(); // on forward change
|
state.normal = get_normal(); // on forward change
|
||||||
state.direction = get_direction(); // on forward/normal/pitch change
|
state.direction = get_direction(); // on forward/normal/pitch change
|
||||||
|
|
||||||
// position
|
// position
|
||||||
state.eye = XMVectorSet(-45.5f, 43.25f, 63.0f, 1);
|
state.eye = XMVectorSet(4.71f, 65.30, 57.92, 1);
|
||||||
state.at = state.eye + state.direction * at_distance;
|
state.at = state.eye + state.direction * at_distance;
|
||||||
//state.at = XMVectorSet(0, 0, 0, 1);
|
//state.at = XMVectorSet(0, 0, 0, 1);
|
||||||
//state.eye = XMVectorSet(0, -100, 0, 1);
|
//state.eye = XMVectorSet(0, -100, 0, 1);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user