Use renderpass to render layers above ghosts

CURA-1601
This commit is contained in:
fieldOfView 2016-08-02 14:31:17 +02:00
parent 90a1f5f8ed
commit b090eab221
3 changed files with 203 additions and 23 deletions

View file

@ -0,0 +1,86 @@
# Copyright (c) 2015 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Resources import Resources
from UM.Scene.SceneNode import SceneNode
from UM.Scene.ToolHandle import ToolHandle
from UM.Application import Application
from UM.View.RenderPass import RenderPass
from UM.View.RenderBatch import RenderBatch
from UM.View.GL.OpenGL import OpenGL
## RenderPass used to display g-code paths.
class LayerPass(RenderPass):
def __init__(self, width, height):
super().__init__("layerview", width, height)
self._shader = None
self._tool_handle_shader = None
self._gl = OpenGL.getInstance().getBindingsObject()
self._scene = Application.getInstance().getController().getScene()
self._layerview = None
def setLayerView(self, layerview):
self._layerview = layerview
def render(self):
if not self._shader:
self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "default.shader"))
if not self._tool_handle_shader:
self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "toolhandle.shader"))
self.bind()
self._gl.glDisable(self._gl.GL_DEPTH_TEST)
tool_handle_batch = RenderBatch(self._tool_handle_shader, type = RenderBatch.RenderType.Overlay)
tool_handle_has_items = False
for node in DepthFirstIterator(self._scene.getRoot()):
if isinstance(node, ToolHandle):
tool_handle_batch.addItem(node.getWorldTransformation(), mesh = node.getSolidMesh())
tool_handle_has_items = True
if type(node) is SceneNode and node.getMeshData() and node.isVisible():
layer_data = node.callDecoration("getLayerData")
if not layer_data:
continue
# Render all layers below a certain number as line mesh instead of vertices.
if self._layerview._current_layer_num - self._layerview._solid_layers > -1 and not self._layerview._only_show_top_layers:
start = 0
end = 0
element_counts = layer_data.getElementCounts()
for layer, counts in element_counts.items():
if layer + self._layerview._solid_layers > self._layerview._current_layer_num:
break
end += counts
# This uses glDrawRangeElements internally to only draw a certain range of lines.
batch = RenderBatch(self._shader, type = RenderBatch.RenderType.NoType, mode = RenderBatch.RenderMode.Lines, range = (start, end))
batch.addItem(node.getWorldTransformation(), layer_data)
batch.render(self._scene.getActiveCamera())
# Create a new batch that is not range-limited
batch = RenderBatch(self._shader, type = RenderBatch.RenderType.NoType, mode = RenderBatch.RenderMode.Lines)
batch_has_items = False
if self._layerview._current_layer_mesh:
batch_has_items = True
batch.addItem(node.getWorldTransformation(), self._layerview._current_layer_mesh)
if self._layerview._current_layer_jumps:
batch_has_items = True
batch.addItem(node.getWorldTransformation(), self._layerview._current_layer_jumps)
if batch_has_items:
batch.render(self._scene.getActiveCamera())
# Render toolhandles on top of the layerview
if tool_handle_has_items:
tool_handle_batch.render(self._scene.getActiveCamera())
self._gl.glEnable(self._gl.GL_DEPTH_TEST)
self.release()

View file

@ -1,6 +1,7 @@
# Copyright (c) 2015 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.
from UM.PluginRegistry import PluginRegistry
from UM.View.View import View
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Resources import Resources
@ -26,14 +27,16 @@ from . import LayerViewProxy
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
from . import LayerPass
import numpy
import os.path
## View used to display g-code paths.
class LayerView(View):
def __init__(self):
super().__init__()
self._shader = None
self._ghost_shader = None
self._num_layers = 0
self._layer_percentage = 0 # what percentage of layers need to be shown (Slider gives value between 0 - 100)
self._proxy = LayerViewProxy.LayerViewProxy()
@ -46,6 +49,13 @@ class LayerView(View):
self._activity = False
self._old_max_layers = 0
self._ghost_shader = None
self._ghost_pass = None
self._composite_pass = None
self._old_layer_bindings = None
self._layerview_composite_shader = None
self._old_composite_shader = None
Preferences.getInstance().addPreference("view/top_layer_count", 5)
Preferences.getInstance().addPreference("view/only_show_top_layers", False)
Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged)
@ -87,6 +97,7 @@ class LayerView(View):
if not self._ghost_shader:
self._ghost_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "color.shader"))
self._ghost_shader.setUniformValue("u_color", Color(32, 32, 32, 96))
for node in DepthFirstIterator(scene.getRoot()):
# We do not want to render ConvexHullNode as it conflicts with the bottom layers.
# However, it is somewhat relevant when the node is selected, so do render it then.
@ -96,28 +107,6 @@ class LayerView(View):
if not node.render(renderer):
if node.getMeshData() and node.isVisible():
renderer.queueNode(node, transparent = True, shader = self._ghost_shader)
layer_data = node.callDecoration("getLayerData")
if not layer_data:
continue
# Render all layers below a certain number as line mesh instead of vertices.
if self._current_layer_num - self._solid_layers > -1 and not self._only_show_top_layers:
start = 0
end = 0
element_counts = layer_data.getElementCounts()
for layer, counts in element_counts.items():
if layer + self._solid_layers > self._current_layer_num:
break
end += counts
# This uses glDrawRangeElements internally to only draw a certain range of lines.
renderer.queueNode(node, mesh = layer_data, mode = RenderBatch.RenderMode.Lines, overlay = True, range = (start, end))
if self._current_layer_mesh:
renderer.queueNode(node, mesh = self._current_layer_mesh, overlay = True)
if self._current_layer_jumps:
renderer.queueNode(node, mesh = self._current_layer_jumps, overlay = True)
def setLayer(self, value):
if self._current_layer_num != value:
@ -182,6 +171,31 @@ class LayerView(View):
self.setLayer(self._current_layer_num - 1)
return True
if event.type == Event.ViewActivateEvent:
if not self._ghost_pass:
# Currently the RenderPass constructor requires a size > 0
# This should be fixed in RenderPass's constructor.
self._ghost_pass = LayerPass.LayerPass(1, 1)
self._ghost_pass.setLayerView(self)
self.getRenderer().addRenderPass(self._ghost_pass)
if not self._layerview_composite_shader:
self._layerview_composite_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("LayerView"), "layerview_composite.shader"))
if not self._composite_pass:
self._composite_pass = self.getRenderer().getRenderPass("composite")
self._old_layer_bindings = self._composite_pass.getLayerBindings()
layer_bindings = self._old_layer_bindings[:] # make a copy
layer_bindings.append("layerview")
self._composite_pass.setLayerBindings(layer_bindings)
self._old_composite_shader = self._composite_pass.getCompositeShader()
self._composite_pass.setCompositeShader(self._layerview_composite_shader)
if event.type == Event.ViewDeactivateEvent:
self._composite_pass.setLayerBindings(self._old_layer_bindings)
self._composite_pass.setCompositeShader(self._old_composite_shader)
def _startUpdateTopLayers(self):
if self._top_layers_job:
self._top_layers_job.finished.disconnect(self._updateCurrentLayerMesh)

View file

@ -0,0 +1,80 @@
[shaders]
vertex =
uniform highp mat4 u_modelViewProjectionMatrix;
attribute highp vec4 a_vertex;
attribute highp vec2 a_uvs;
varying highp vec2 v_uvs;
void main()
{
gl_Position = u_modelViewProjectionMatrix * a_vertex;
v_uvs = a_uvs;
}
fragment =
uniform sampler2D u_layer0;
uniform sampler2D u_layer1;
uniform sampler2D u_layer2;
uniform sampler2D u_layer3;
uniform float u_imageWidth;
uniform float u_imageHeight;
uniform vec2 u_offset[9];
uniform float u_outline_strength;
uniform vec4 u_outline_color;
varying vec2 v_uvs;
float kernel[9];
const vec3 x_axis = vec3(1.0, 0.0, 0.0);
const vec3 y_axis = vec3(0.0, 1.0, 0.0);
const vec3 z_axis = vec3(0.0, 0.0, 1.0);
void main()
{
kernel[0] = 0.0; kernel[1] = 1.0; kernel[2] = 0.0;
kernel[3] = 1.0; kernel[4] = -4.0; kernel[5] = 1.0;
kernel[6] = 0.0; kernel[7] = 1.0; kernel[8] = 0.0;
vec4 result = vec4(0.965, 0.965, 0.965, 1.0);
vec4 layer0 = texture2D(u_layer0, v_uvs);
vec4 layer2 = texture2D(u_layer2, v_uvs);
result = layer0 * layer0.a + result * (1.0 - layer0.a);
result = layer2 * layer2.a + result * (1.0 - layer2.a);
vec4 sum = vec4(0.0);
for (int i = 0; i < 9; i++)
{
vec4 color = vec4(texture2D(u_layer1, v_uvs.xy + u_offset[i]).a);
sum += color * (kernel[i] / u_outline_strength);
}
vec4 layer1 = texture2D(u_layer1, v_uvs);
if((layer1.rgb == x_axis || layer1.rgb == y_axis || layer1.rgb == z_axis))
{
gl_FragColor = result;
}
else
{
gl_FragColor = mix(result, u_outline_color, abs(sum.a));
}
}
[defaults]
u_layer0 = 0
u_layer1 = 1
u_layer2 = 2
u_layer3 = 3
u_outline_strength = 1.0
u_outline_color = [0.05, 0.66, 0.89, 1.0]
[bindings]
[attributes]
a_vertex = vertex
a_uvs = uv