diff --git a/GLMakie/assets/shader/voxel.frag b/GLMakie/assets/shader/voxel.frag index adf3f5b018f..766e6c9e91b 100644 --- a/GLMakie/assets/shader/voxel.frag +++ b/GLMakie/assets/shader/voxel.frag @@ -2,18 +2,29 @@ // {{GLSL VERSION}} // {{GLSL_EXTENSIONS}} -in vec3 f_normal; -in vec3 f_uvw; +struct Nothing{ //Nothing type, to encode if some variable doesn't contain any data + bool _; //empty structs are not allowed +}; + +// Sets which shading procedures to use +{{shading}} + +in vec3 o_normal; +in vec3 o_uvw; uniform isampler3D voxel_id; uniform uint objectid; void write2framebuffer(vec4 color, uvec2 id); +#ifndef NO_SHADING +vec3 illuminate(vec3 normal, vec3 base_color); +#endif + void main() { // grab voxel id - uint id = uint(texture(voxel_id, f_uvw).x); + uint id = uint(texture(voxel_id, o_uvw).x); // id is invisible so we simply discard if (id == uint(0)) { @@ -21,18 +32,21 @@ void main() } // otherwise we draw. For now just some color... - vec4 color = vec4( + vec3 color = vec3( float((id & uint(225)) >> uint(5)) / 5.0, float((id & uint(25)) >> uint(3)) / 3.0, - float((id & uint(7)) >> uint(1)) / 3.0, - 1.0 + float((id & uint(7)) >> uint(1)) / 3.0 ); + #ifndef NO_SHADING + color = illuminate(o_normal, color); + #endif + // TODO: index into 3d array uvec3 size = uvec3(textureSize(voxel_id, 0).xyz); - uvec3 idx = uvec3(f_uvw * size); + uvec3 idx = uvec3(o_uvw * size); uint lin = uint(1) + idx.x + size.x * (idx.y + size.y * idx.z); // draw - write2framebuffer(color, uvec2(objectid, lin)); + write2framebuffer(vec4(color, 1.0), uvec2(objectid, lin)); } \ No newline at end of file diff --git a/GLMakie/assets/shader/voxel.vert b/GLMakie/assets/shader/voxel.vert index 92320fb87fa..6cc5fbc5943 100644 --- a/GLMakie/assets/shader/voxel.vert +++ b/GLMakie/assets/shader/voxel.vert @@ -4,8 +4,10 @@ in vec2 vertices; -flat out vec3 f_normal; -out vec3 f_uvw; +flat out vec3 o_normal; +out vec3 o_uvw; +out vec3 o_camdir; +out vec3 o_world_pos; uniform mat4 model; uniform mat3 world_normalmatrix; @@ -74,6 +76,7 @@ void main() { vec3 displacement = id * unit_vecs[dim]; vec3 voxel_pos = size * (orientations[dim] * vertices) + displacement; vec4 world_pos = model * vec4(voxel_pos, 1.0f); + o_world_pos = world_pos.xyz; gl_Position = projectionview * world_pos; gl_Position.z += gl_Position.w * depth_shift; @@ -83,8 +86,8 @@ void main() { // If we assume the viewer to be outside of a voxel, the normal direction // should always be facing them. Thus: vec3 n = world_normalmatrix * unit_vecs[dim]; - vec3 camdir = eyeposition - world_pos.xyz / world_pos.w; - f_normal = normalize(sign(dot(camdir, n)) * n); + o_camdir = eyeposition - world_pos.xyz / world_pos.w; + o_normal = normalize(sign(dot(o_camdir, n)) * n); // The texture coordinate can also be derived. `voxel_pos` effectively gives // an integer index into the chunk, shifted to be centered. We can convert @@ -98,7 +101,7 @@ void main() { // | 1 | 2 | 0 | v // If we shift in +normal direction (towards viewer) the planes would sample // from the id closer to the viewer, drawing a backface. - f_uvw = (voxel_pos - 0.5 * f_normal) / size + 0.5; + o_uvw = (voxel_pos - 0.5 * o_normal) / size + 0.5; // TODO: // - verify no missing faces (we are missing 3 planes I think, but that should be possible...) diff --git a/GLMakie/src/glshaders/voxel.jl b/GLMakie/src/glshaders/voxel.jl index cf28b04bd9e..6b5fb21883f 100644 --- a/GLMakie/src/glshaders/voxel.jl +++ b/GLMakie/src/glshaders/voxel.jl @@ -18,16 +18,16 @@ function draw_voxels(screen, main::VolumeTypes, data::Dict) voxel_id = main => Texture instances = const_lift(t -> sum(size(t)) + 3, voxel_id) model = Mat4f(I) - # modelinv = const_lift(inv, model) transparency = false + backlight = 0f0 shader = GLVisualizeShader( screen, "voxel.vert", - "fragment_output.frag", "voxel.frag", # "lighting.frag", "volume.frag", + "fragment_output.frag", "voxel.frag", "lighting.frag", view = Dict( - # "shading" => light_calc(shading), - # "MAX_LIGHTS" => "#define MAX_LIGHTS $(screen.config.max_lights)", - # "MAX_LIGHT_PARAMETERS" => "#define MAX_LIGHT_PARAMETERS $(screen.config.max_light_parameters)", + "shading" => light_calc(shading), + "MAX_LIGHTS" => "#define MAX_LIGHTS $(screen.config.max_lights)", + "MAX_LIGHT_PARAMETERS" => "#define MAX_LIGHT_PARAMETERS $(screen.config.max_light_parameters)", "buffers" => output_buffers(screen, to_value(transparency)), "buffer_writes" => output_buffer_writes(screen, to_value(transparency)) )