From 26e09c9f01eaf997b0b4f8fa831ed3873f66465a Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Sat, 28 Mar 2020 19:55:14 +0100 Subject: Draw spheres in correct size …using billboarding. --- boltzgas/visual/shader.py | 15 ++++++++- boltzgas/visual/view.py | 78 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 74 insertions(+), 19 deletions(-) diff --git a/boltzgas/visual/shader.py b/boltzgas/visual/shader.py index b4295a8..c6c035b 100644 --- a/boltzgas/visual/shader.py +++ b/boltzgas/visual/shader.py @@ -1,4 +1,4 @@ -from OpenGL.GL import GL_VERTEX_SHADER, GL_FRAGMENT_SHADER +from OpenGL.GL import GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, GL_GEOMETRY_SHADER from OpenGL.GL import shaders class Shader: @@ -13,3 +13,16 @@ class Shader: def use(self): shaders.glUseProgram(self.program) +class GeometryShader: + def __init__(self, fragment_src, geometry_src, vertex_src, uniform): + self.program = shaders.compileProgram( + shaders.compileShader(vertex_src, GL_VERTEX_SHADER), + shaders.compileShader(geometry_src, GL_GEOMETRY_SHADER), + shaders.compileShader(fragment_src, GL_FRAGMENT_SHADER)) + self.uniform = { } + for name in uniform: + self.uniform[name] = shaders.glGetUniformLocation(self.program, name) + + def use(self): + shaders.glUseProgram(self.program) + diff --git a/boltzgas/visual/view.py b/boltzgas/visual/view.py index bdc18e8..7d7d2cc 100644 --- a/boltzgas/visual/view.py +++ b/boltzgas/visual/view.py @@ -5,7 +5,7 @@ from pyrr import matrix44 import numpy as np -from .shader import Shader +from .shader import Shader, GeometryShader from .camera import Projection, Rotation, MouseDragMonitor, MouseScrollMonitor particle_shader = ( @@ -16,43 +16,86 @@ particle_shader = ( uniform vec4 camera_pos; + in GS_OUT + { + vec3 particle_pos; + vec2 tex_coord; + } fs_in; + void main(){ - if (length(gl_PointCoord - vec2(0.5)) > 0.5) { + if (length(fs_in.tex_coord - vec2(0.5)) > 0.5) { discard; } - vec3 n = vec3(gl_PointCoord - vec2(0.5), 0.); + vec3 n = vec3(fs_in.tex_coord - vec2(0.5), 0.); n.z = -sqrt(1.0 - length(n)); n = normalize(n); - vec3 dir = normalize(camera_pos.xyz - particle_pos); - vec3 color = vec3(1.) * dot(dir, n); + vec3 dir = normalize(camera_pos.xyz - fs_in.particle_pos); + vec3 color = vec3(1.) * max(0., dot(dir, n)); - gl_FragColor = vec4(max(vec3(0.5), color.xyz), 1.0); + gl_FragColor = vec4(color.xyz, 1.0); } """, """ #version 430 - layout (location=0) in vec4 particles; + layout (points) in; + layout (triangle_strip, max_vertices=4) out; - out vec3 color; - out vec3 particle_pos; + out GS_OUT + { + vec3 particle_pos; + vec2 tex_coord; + } gs_out; uniform mat4 projection; uniform mat4 rotation; - uniform vec3 face_color; - uniform vec3 trace_color; - uniform uint trace_id; uniform vec4 camera_pos; + uniform float radius; + + vec4 project(vec3 v) { + return projection * rotation * vec4(v, 1.); + } + + void emitSquareAt(vec3 position) { + mat4 m = projection * rotation; + vec3 camera_right = normalize(vec3(m[0][0], m[1][0], m[2][0])); + vec3 camera_up = normalize(vec3(m[0][1], m[1][1], m[2][1])); + + gs_out.particle_pos = gl_in[0].gl_Position.xyz; + + gl_Position = project(position + camera_right * -radius + camera_up * -radius); + gs_out.tex_coord = vec2(0.,0.); + EmitVertex(); + gl_Position = project(position + camera_right * radius + camera_up * -radius); + gs_out.tex_coord = vec2(1.,0.); + EmitVertex(); + gl_Position = project(position + camera_right * -radius + camera_up * radius); + gs_out.tex_coord = vec2(0.,1.); + EmitVertex(); + gl_Position = project(position + camera_right * radius + camera_up * radius); + gs_out.tex_coord = vec2(1.,1.); + EmitVertex(); + } + + void main() { + emitSquareAt(gl_in[0].gl_Position.xyz); + EndPrimitive(); + } + """, + """ + #version 430 + + layout (location=0) in vec4 particle_pos; + void main() { - gl_Position = projection * rotation * vec4(particles.xyz, 1.); - particle_pos = gl_Position.xyz; + gl_Position = vec4(particle_pos.xyz, 1.0); } """, - ['projection', 'rotation', 'camera_pos'] + ['projection', 'rotation', 'camera_pos', 'radius'] ) decoration_shader = ( @@ -122,7 +165,7 @@ class View: self.instruments = instruments self.texture_shader = Shader(*texture_shader) - self.particle_shader = Shader(*particle_shader) + self.particle_shader = GeometryShader(*particle_shader) self.decoration_shader = Shader(*decoration_shader) self.camera_projection = Projection(distance = 5) @@ -169,9 +212,8 @@ class View: glUniformMatrix4fv(self.particle_shader.uniform['projection'], 1, False, np.ascontiguousarray(self.camera_projection.get())) glUniformMatrix4fv(self.particle_shader.uniform['rotation'], 1, False, np.ascontiguousarray(self.camera_rotation.get())) glUniform4fv(self.particle_shader.uniform['camera_pos'], 1, self.camera_pos) + glUniform1f(self.particle_shader.uniform['radius'], self.gas.radius) - glEnable(GL_POINT_SPRITE) - glPointSize(2*self.gas.radius*self.pixels_per_unit) self.gas.gl_draw_particles() glBindVertexArray(0) -- cgit v1.2.3