From e024b7e72c4170e84e689b530f18f2f03c1f1b35 Mon Sep 17 00:00:00 2001 From: Matthew Turk Date: Fri, 16 Dec 2022 14:17:52 -0600 Subject: [PATCH 1/5] First draft of vmcontainer --- yt_idv/scene_data/variable_mesh.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 yt_idv/scene_data/variable_mesh.py diff --git a/yt_idv/scene_data/variable_mesh.py b/yt_idv/scene_data/variable_mesh.py new file mode 100644 index 0000000..20d5842 --- /dev/null +++ b/yt_idv/scene_data/variable_mesh.py @@ -0,0 +1,27 @@ +import numpy as np +import traitlets +from yt.data_objects.selection_objects.data_selection_objects import ( + YTSelectionContainer2D, +) +from yt_idv.scene_data.base_data import SceneData +from yt_idv.opengl_support import VertexArray, VertexAttribute + + +class VariableMeshContainer(SceneData): + name = "variable_mesh" + data_source = traitlets.Instance(YTSelectionContainer2D) + + @traitlets.default("vertex_array") + def _default_vertex_array(self): + rv = VertexArray(name="vm_positions", each=1) + + def add_data(self, field): + if len(self.vertex_array.attributes) > 0: + # Has already been initialized, so we just update the data + self.vertex_array.attributes[-1].data = self.data_source[field].astype("f4") + return + for vfield in ("px", "py", "pdx", "pdy"): + self.vertex_array.attributes.append( + VertexAttribute(name=vfield, data=self.data_source[vfield].astype("f4") + ) + self.vertex_array.attributes.append(VertexAttribute(name = "field", data = self.data_source[field].astype("f4"))) From d4dc21e9d954db6016319f5a6553e43b8d9b1310 Mon Sep 17 00:00:00 2001 From: Matthew Turk Date: Mon, 19 Dec 2022 17:00:59 -0600 Subject: [PATCH 2/5] initial ideas for displaying vm --- .../scene_components/variable_mesh_display.py | 21 +++++ yt_idv/shaders/variable_mesh_expand.geom.glsl | 81 +++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 yt_idv/scene_components/variable_mesh_display.py create mode 100644 yt_idv/shaders/variable_mesh_expand.geom.glsl diff --git a/yt_idv/scene_components/variable_mesh_display.py b/yt_idv/scene_components/variable_mesh_display.py new file mode 100644 index 0000000..ba792e2 --- /dev/null +++ b/yt_idv/scene_components/variable_mesh_display.py @@ -0,0 +1,21 @@ +import numpy as np +import traitlets +from OpenGL import GL + +from yt_idv.scene_components.base_component import SceneComponent +from yt_idv.scene_data.variable_mesh import VariableMeshContainer + + +class VariableMeshDisplay(SceneComponent): + """ + A class that renders variable mesh datasets. + """ + + name = "variable_mesh_display" + data = traitlets.Instance(VariableMeshContainer) + priority = 11 + + def draw(self, scene, program): + GL.glEnable(GL.GL_CULL_FACE) + GL.glCullFace(GL.GL_BACK) + GL.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4, self.data.size) \ No newline at end of file diff --git a/yt_idv/shaders/variable_mesh_expand.geom.glsl b/yt_idv/shaders/variable_mesh_expand.geom.glsl new file mode 100644 index 0000000..3a796ee --- /dev/null +++ b/yt_idv/shaders/variable_mesh_expand.geom.glsl @@ -0,0 +1,81 @@ +layout ( points ) in; +layout ( triangle_strip, max_vertices = 4 ) out; + +flat in float vradius[]; +flat in float vfield_value[]; + +flat out mat4 inverse_proj; +flat out mat4 inverse_mvm; +flat out mat4 inverse_pmvm; +flat out vec4 v_model; +flat out float field_value; +flat out float radius; + +out vec2 UV; + +flat in mat4 vinverse_proj[]; +flat in mat4 vinverse_mvm[]; +flat in mat4 vinverse_pmvm[]; +flat in vec4 vv_model[]; +flat in vec3 vv_camera_pos[]; + +// https://stackoverflow.com/questions/28375338/cube-using-single-gl-triangle-strip +// suggests that the triangle strip we want for the cube is + +void main() { + + vec4 cornerPos; + vec2 cornerFrag; + vec4 position = vv_model[0]; + mat4 pmvm = projection * modelview; + + // This is our inverse projection model view matrix. That means that if we + // move something in clip space and multiply by this, it becomes the world + // coordinates of that new thing. + // + // We want to figure out what the world vectors corresponding to clip space + // motion (at the z and w of our current vertex) are. + vec4 fragLeftCorner = pmvm * (position + vradius[0] * normalize(vinverse_pmvm[0] * vec4(-1.0, -1.0, gl_in[0].gl_Position.zw))); + vec4 fragRightCorner = pmvm * (position + vradius[0] * normalize(vinverse_pmvm[0] * vec4(1.0, 1.0, gl_in[0].gl_Position.zw))); + + // We don't want to allow each particle to be bigger than some maximum size + // in clip space coordinates. + + fragLeftCorner.x = max(fragLeftCorner.x, gl_in[0].gl_Position.x - max_particle_size/2.0); + fragLeftCorner.y = max(fragLeftCorner.y, gl_in[0].gl_Position.y - max_particle_size/2.0); + fragRightCorner.x = min(fragRightCorner.x, gl_in[0].gl_Position.x + max_particle_size/2.0); + fragRightCorner.y = min(fragRightCorner.y, gl_in[0].gl_Position.y + max_particle_size/2.0); + + // https://stackoverflow.com/questions/12239876/fastest-way-of-converting-a-quad-to-a-triangle-strip + // or: https://en.wikipedia.org/wiki/Triangle_strip + // in section "OpenGL implementation" this corresponds to A = 1, B = 2, C = 3, D = 4 + + gl_Position = vec4(fragLeftCorner.xy, gl_in[0].gl_Position.zw); + field_value = vfield_value[0]; + v_model = vv_model[0]; + radius = vradius[0]; + UV = vec2(-1.0, -1.0); + EmitVertex(); + + gl_Position = vec4(fragLeftCorner.x, fragRightCorner.y, gl_in[0].gl_Position.zw); + field_value = vfield_value[0]; + v_model = vv_model[0]; + radius = vradius[0]; + UV = vec2(-1.0, +1.0); + EmitVertex(); + + gl_Position = vec4(fragRightCorner.x, fragLeftCorner.y, gl_in[0].gl_Position.zw); + field_value = vfield_value[0]; + v_model = vv_model[0]; + radius = vradius[0]; + UV = vec2(+1.0, -1.0); + EmitVertex(); + + gl_Position = vec4(fragRightCorner.xy, gl_in[0].gl_Position.zw); + field_value = vfield_value[0]; + v_model = vv_model[0]; + radius = vradius[0]; + UV = vec2(+1.0, +1.0); + EmitVertex(); + +} From 3c64812f78c33d40eed0dc947bea17b83615e678 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 Dec 2022 23:01:40 +0000 Subject: [PATCH 3/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- yt_idv/scene_components/variable_mesh_display.py | 2 +- yt_idv/scene_data/variable_mesh.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/yt_idv/scene_components/variable_mesh_display.py b/yt_idv/scene_components/variable_mesh_display.py index ba792e2..5ecb527 100644 --- a/yt_idv/scene_components/variable_mesh_display.py +++ b/yt_idv/scene_components/variable_mesh_display.py @@ -18,4 +18,4 @@ class VariableMeshDisplay(SceneComponent): def draw(self, scene, program): GL.glEnable(GL.GL_CULL_FACE) GL.glCullFace(GL.GL_BACK) - GL.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4, self.data.size) \ No newline at end of file + GL.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4, self.data.size) diff --git a/yt_idv/scene_data/variable_mesh.py b/yt_idv/scene_data/variable_mesh.py index 20d5842..0819bf3 100644 --- a/yt_idv/scene_data/variable_mesh.py +++ b/yt_idv/scene_data/variable_mesh.py @@ -3,8 +3,9 @@ from yt.data_objects.selection_objects.data_selection_objects import ( YTSelectionContainer2D, ) -from yt_idv.scene_data.base_data import SceneData + from yt_idv.opengl_support import VertexArray, VertexAttribute +from yt_idv.scene_data.base_data import SceneData class VariableMeshContainer(SceneData): From 8cb85309d9722045384da57f7cf0b2576aa5af48 Mon Sep 17 00:00:00 2001 From: Matthew Turk Date: Tue, 6 Jun 2023 17:06:54 -0500 Subject: [PATCH 4/5] Working on further variable mesh viewer functionality --- examples/variable_mesh_viewer.py | 20 +++++ .../scene_components/variable_mesh_display.py | 5 +- yt_idv/scene_data/variable_mesh.py | 5 +- yt_idv/shaders/shaderlist.yaml | 23 +++++ yt_idv/shaders/variable_mesh.frag.glsl | 8 ++ yt_idv/shaders/variable_mesh.vert.glsl | 15 ++++ yt_idv/shaders/variable_mesh_expand.geom.glsl | 88 +++++++------------ 7 files changed, 105 insertions(+), 59 deletions(-) create mode 100644 examples/variable_mesh_viewer.py create mode 100644 yt_idv/shaders/variable_mesh.frag.glsl create mode 100644 yt_idv/shaders/variable_mesh.vert.glsl diff --git a/examples/variable_mesh_viewer.py b/examples/variable_mesh_viewer.py new file mode 100644 index 0000000..158da7b --- /dev/null +++ b/examples/variable_mesh_viewer.py @@ -0,0 +1,20 @@ +import yt +import yt_idv +from yt_idv.scene_data.variable_mesh import VariableMeshContainer +from yt_idv.scene_components.variable_mesh_display import VariableMeshDisplay + +ds = yt.load_sample("IsolatedGalaxy") + +vm = ds.r[:,:,0.5] + +rc = yt_idv.render_context(height=800, width=800, gui=True) +sg = rc.add_scene(ds, None) + +vmc = VariableMeshContainer(data_source = vm) +vmc.add_data("ones") +vmd = VariableMeshDisplay(data = vmc) + +sg.data_objects.append(vmc) +sg.components.append(vmd) + +rc.run() diff --git a/yt_idv/scene_components/variable_mesh_display.py b/yt_idv/scene_components/variable_mesh_display.py index 5ecb527..d52d77c 100644 --- a/yt_idv/scene_components/variable_mesh_display.py +++ b/yt_idv/scene_components/variable_mesh_display.py @@ -18,4 +18,7 @@ class VariableMeshDisplay(SceneComponent): def draw(self, scene, program): GL.glEnable(GL.GL_CULL_FACE) GL.glCullFace(GL.GL_BACK) - GL.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4, self.data.size) + GL.glDrawArraysInstanced(GL.GL_TRIANGLE_STRIP, 0, 4, self.data.size) + + def _set_uniforms(self, scene, program): + pass diff --git a/yt_idv/scene_data/variable_mesh.py b/yt_idv/scene_data/variable_mesh.py index 0819bf3..fe4da68 100644 --- a/yt_idv/scene_data/variable_mesh.py +++ b/yt_idv/scene_data/variable_mesh.py @@ -15,6 +15,7 @@ class VariableMeshContainer(SceneData): @traitlets.default("vertex_array") def _default_vertex_array(self): rv = VertexArray(name="vm_positions", each=1) + return rv def add_data(self, field): if len(self.vertex_array.attributes) > 0: @@ -22,7 +23,9 @@ def add_data(self, field): self.vertex_array.attributes[-1].data = self.data_source[field].astype("f4") return for vfield in ("px", "py", "pdx", "pdy"): + f = self.data_source[vfield].in_units('unitary').astype("f4") self.vertex_array.attributes.append( - VertexAttribute(name=vfield, data=self.data_source[vfield].astype("f4") + VertexAttribute(name=vfield, data=f) ) self.vertex_array.attributes.append(VertexAttribute(name = "field", data = self.data_source[field].astype("f4"))) + self.size = self.data_source['px'].size diff --git a/yt_idv/shaders/shaderlist.yaml b/yt_idv/shaders/shaderlist.yaml index 52f52eb..19fea8a 100644 --- a/yt_idv/shaders/shaderlist.yaml +++ b/yt_idv/shaders/shaderlist.yaml @@ -133,6 +133,13 @@ shader_definitions: - one - zero blend_equation: func add + variable_mesh: + info: Sample a flat field value + source: variable_mesh.frag.glsl + depth_test: less + blend_func: + - one + - zero vertex: default: info: A first pass vertex shader that tranlates the location of vertices from @@ -160,6 +167,9 @@ shader_definitions: octree_position: info: Expect instanced rendering of octree nodes source: octree_position.vert.glsl + variable_mesh: + info: Billboard some variable mesh values + source: variable_mesh.vert.glsl geometry: grid_expand: info: Expand grid left and right edges into a set of triangles @@ -167,6 +177,9 @@ shader_definitions: particle_expand: info: Expand particles from points to triangulated quads source: particle_expand.geom.glsl + variable_mesh_expand: + info: Expand variable mesh points to quads + source: variable_mesh_expand.geom.glsl component_shaders: curve_rendering: default_value: default @@ -315,3 +328,13 @@ component_shaders: first_fragment: field_value second_vertex: passthrough second_fragment: apply_colormap + variable_mesh_display: + default_value: default + default: + description: Display variable mesh as quads + first_vertex: variable_mesh + first_geometry: variable_mesh_expand + first_fragment: variable_mesh + second_vertex: passthrough + second_fragment: apply_colormap + diff --git a/yt_idv/shaders/variable_mesh.frag.glsl b/yt_idv/shaders/variable_mesh.frag.glsl new file mode 100644 index 0000000..3e4b03d --- /dev/null +++ b/yt_idv/shaders/variable_mesh.frag.glsl @@ -0,0 +1,8 @@ +flat in vec4 v_model; +flat in float field_value; +out vec4 output_color; + +void main() +{ + output_color = vec4(field_value); +} diff --git a/yt_idv/shaders/variable_mesh.vert.glsl b/yt_idv/shaders/variable_mesh.vert.glsl new file mode 100644 index 0000000..ec2434c --- /dev/null +++ b/yt_idv/shaders/variable_mesh.vert.glsl @@ -0,0 +1,15 @@ +in float px; +in float py; +in float pdx; +in float pdy; +in float field_value; + +flat out vec4 vv_model; +flat out float vv_field_value; + +void main() +{ + vv_model = vec4(px, py, pdx, pdy); + vv_field_value = field_value; + gl_Position = vec4(px, py, 0.0, 0.0); +} diff --git a/yt_idv/shaders/variable_mesh_expand.geom.glsl b/yt_idv/shaders/variable_mesh_expand.geom.glsl index 3a796ee..dda4464 100644 --- a/yt_idv/shaders/variable_mesh_expand.geom.glsl +++ b/yt_idv/shaders/variable_mesh_expand.geom.glsl @@ -1,81 +1,55 @@ layout ( points ) in; layout ( triangle_strip, max_vertices = 4 ) out; -flat in float vradius[]; -flat in float vfield_value[]; - -flat out mat4 inverse_proj; -flat out mat4 inverse_mvm; -flat out mat4 inverse_pmvm; flat out vec4 v_model; flat out float field_value; -flat out float radius; - -out vec2 UV; -flat in mat4 vinverse_proj[]; -flat in mat4 vinverse_mvm[]; -flat in mat4 vinverse_pmvm[]; flat in vec4 vv_model[]; -flat in vec3 vv_camera_pos[]; +flat in float vv_field_value[]; -// https://stackoverflow.com/questions/28375338/cube-using-single-gl-triangle-strip -// suggests that the triangle strip we want for the cube is void main() { - vec4 cornerPos; - vec2 cornerFrag; - vec4 position = vv_model[0]; - mat4 pmvm = projection * modelview; - - // This is our inverse projection model view matrix. That means that if we - // move something in clip space and multiply by this, it becomes the world - // coordinates of that new thing. - // - // We want to figure out what the world vectors corresponding to clip space - // motion (at the z and w of our current vertex) are. - vec4 fragLeftCorner = pmvm * (position + vradius[0] * normalize(vinverse_pmvm[0] * vec4(-1.0, -1.0, gl_in[0].gl_Position.zw))); - vec4 fragRightCorner = pmvm * (position + vradius[0] * normalize(vinverse_pmvm[0] * vec4(1.0, 1.0, gl_in[0].gl_Position.zw))); - - // We don't want to allow each particle to be bigger than some maximum size - // in clip space coordinates. - - fragLeftCorner.x = max(fragLeftCorner.x, gl_in[0].gl_Position.x - max_particle_size/2.0); - fragLeftCorner.y = max(fragLeftCorner.y, gl_in[0].gl_Position.y - max_particle_size/2.0); - fragRightCorner.x = min(fragRightCorner.x, gl_in[0].gl_Position.x + max_particle_size/2.0); - fragRightCorner.y = min(fragRightCorner.y, gl_in[0].gl_Position.y + max_particle_size/2.0); - - // https://stackoverflow.com/questions/12239876/fastest-way-of-converting-a-quad-to-a-triangle-strip - // or: https://en.wikipedia.org/wiki/Triangle_strip - // in section "OpenGL implementation" this corresponds to A = 1, B = 2, C = 3, D = 4 - - gl_Position = vec4(fragLeftCorner.xy, gl_in[0].gl_Position.zw); - field_value = vfield_value[0]; + // This is considerably simpler because we will just be doing things based + // on the positions in clip space + gl_Position = vec4( + vv_model[0].x - vv_model[0].z, + vv_model[0].y - vv_model[0].w, + 0.0, + 0.0 + ); + field_value = vv_field_value[0]; v_model = vv_model[0]; - radius = vradius[0]; - UV = vec2(-1.0, -1.0); EmitVertex(); - gl_Position = vec4(fragLeftCorner.x, fragRightCorner.y, gl_in[0].gl_Position.zw); - field_value = vfield_value[0]; + gl_Position = vec4( + vv_model[0].x - vv_model[0].z, + vv_model[0].y + vv_model[0].w, + 0.0, + 0.0 + ); + field_value = vv_field_value[0]; v_model = vv_model[0]; - radius = vradius[0]; - UV = vec2(-1.0, +1.0); EmitVertex(); - gl_Position = vec4(fragRightCorner.x, fragLeftCorner.y, gl_in[0].gl_Position.zw); - field_value = vfield_value[0]; + gl_Position = vec4( + vv_model[0].x + vv_model[0].z, + vv_model[0].y + vv_model[0].w, + 0.0, + 0.0 + ); + field_value = vv_field_value[0]; v_model = vv_model[0]; - radius = vradius[0]; - UV = vec2(+1.0, -1.0); EmitVertex(); - gl_Position = vec4(fragRightCorner.xy, gl_in[0].gl_Position.zw); - field_value = vfield_value[0]; + gl_Position = vec4( + vv_model[0].x + vv_model[0].z, + vv_model[0].y - vv_model[0].w, + 0.0, + 0.0 + ); + field_value = vv_field_value[0]; v_model = vv_model[0]; - radius = vradius[0]; - UV = vec2(+1.0, +1.0); EmitVertex(); } From 1c20dfedafa08531544b64a6025d64a590934c1a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 6 Jun 2023 22:07:19 +0000 Subject: [PATCH 5/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- examples/variable_mesh_viewer.py | 9 +++++---- yt_idv/scene_data/variable_mesh.py | 12 ++++++------ yt_idv/shaders/shaderlist.yaml | 1 - 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/variable_mesh_viewer.py b/examples/variable_mesh_viewer.py index 158da7b..f433899 100644 --- a/examples/variable_mesh_viewer.py +++ b/examples/variable_mesh_viewer.py @@ -1,18 +1,19 @@ import yt + import yt_idv -from yt_idv.scene_data.variable_mesh import VariableMeshContainer from yt_idv.scene_components.variable_mesh_display import VariableMeshDisplay +from yt_idv.scene_data.variable_mesh import VariableMeshContainer ds = yt.load_sample("IsolatedGalaxy") -vm = ds.r[:,:,0.5] +vm = ds.r[:, :, 0.5] rc = yt_idv.render_context(height=800, width=800, gui=True) sg = rc.add_scene(ds, None) -vmc = VariableMeshContainer(data_source = vm) +vmc = VariableMeshContainer(data_source=vm) vmc.add_data("ones") -vmd = VariableMeshDisplay(data = vmc) +vmd = VariableMeshDisplay(data=vmc) sg.data_objects.append(vmc) sg.components.append(vmd) diff --git a/yt_idv/scene_data/variable_mesh.py b/yt_idv/scene_data/variable_mesh.py index fe4da68..7a37e92 100644 --- a/yt_idv/scene_data/variable_mesh.py +++ b/yt_idv/scene_data/variable_mesh.py @@ -23,9 +23,9 @@ def add_data(self, field): self.vertex_array.attributes[-1].data = self.data_source[field].astype("f4") return for vfield in ("px", "py", "pdx", "pdy"): - f = self.data_source[vfield].in_units('unitary').astype("f4") - self.vertex_array.attributes.append( - VertexAttribute(name=vfield, data=f) - ) - self.vertex_array.attributes.append(VertexAttribute(name = "field", data = self.data_source[field].astype("f4"))) - self.size = self.data_source['px'].size + f = self.data_source[vfield].in_units("unitary").astype("f4") + self.vertex_array.attributes.append(VertexAttribute(name=vfield, data=f)) + self.vertex_array.attributes.append( + VertexAttribute(name="field", data=self.data_source[field].astype("f4")) + ) + self.size = self.data_source["px"].size diff --git a/yt_idv/shaders/shaderlist.yaml b/yt_idv/shaders/shaderlist.yaml index 19fea8a..64a081f 100644 --- a/yt_idv/shaders/shaderlist.yaml +++ b/yt_idv/shaders/shaderlist.yaml @@ -337,4 +337,3 @@ component_shaders: first_fragment: variable_mesh second_vertex: passthrough second_fragment: apply_colormap -