Skip to content

Commit

Permalink
Use VBO colors for ViewEdges shader instead of uniforms. (openscad#5674)
Browse files Browse the repository at this point in the history
* Moved getShaderColor() to Renderer
* Use object colors rather than external color for edge shader
* Calculate edge color from current face color
  • Loading branch information
kintel authored Feb 18, 2025
1 parent 3d6fec9 commit 5d7b26f
Show file tree
Hide file tree
Showing 22 changed files with 93 additions and 67 deletions.
5 changes: 3 additions & 2 deletions shaders/ViewEdges.frag
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#version 120

uniform vec4 color_area, color_edge;
varying vec4 color;
varying vec3 vBC;
varying float shading;

Expand All @@ -19,5 +19,6 @@ float edgeFactor() {
}

void main(void) {
gl_FragColor = mix(color_edge, vec4(color_area.rgb * shading, color_area.a), edgeFactor());
vec4 color_edge = vec4((color.rgb + vec3(1))/2, 1.0);
gl_FragColor = mix(color_edge, vec4(color.rgb * shading, color.a), edgeFactor());
}
4 changes: 3 additions & 1 deletion shaders/ViewEdges.vert
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ attribute vec3 barycentric; // barycentric form of vertex coord
// either [1,0,0], [0,1,0] or [0,0,1] under normal circumstances (no edges disabled)

varying vec3 vBC; // varying barycentric coords
varying float shading; // multiplied by color_ares. color_edge is without lighting
varying float shading; // Will be multiplied by color in fragment shader
varying vec4 color; // per-vertex colors

void main(void) {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
Expand All @@ -13,4 +14,5 @@ void main(void) {
normal = normalize(gl_NormalMatrix * gl_Normal);
lightDir = normalize(vec3(gl_LightSource[0].position));
shading = 0.2 + abs(dot(normal, lightDir));
color = gl_Color;
}
2 changes: 0 additions & 2 deletions src/glview/GLView.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ void GLView::setupShader() {
.resource = resource,
.type = ShaderUtils::ShaderType::EDGE_RENDERING,
.uniforms = {
{"color_area", glGetUniformLocation(resource.shader_program, "color_area")},
{"color_edge", glGetUniformLocation(resource.shader_program, "color_edge")},
},
.attributes = {
{"barycentric", glGetAttribLocation(resource.shader_program, "barycentric")},
Expand Down
38 changes: 35 additions & 3 deletions src/glview/Renderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,46 @@ Renderer::Renderer()
PRINTD("Renderer() end");
}

bool Renderer::getColor(Renderer::ColorMode colormode, Color4f& col) const
bool Renderer::getColorSchemeColor(Renderer::ColorMode colormode, Color4f& outcolor) const
{
if (const auto it = colormap_.find(colormode); it != colormap_.end()) {
col = it->second;
outcolor = it->second;
return true;
}
return false;
}

bool Renderer::getShaderColor(Renderer::ColorMode colormode, const Color4f& object_color,
Color4f& outcolor) const
{
// If an object was colored, use that color, except when using the highlight/background operator
if ((colormode != ColorMode::BACKGROUND) && (colormode != ColorMode::HIGHLIGHT) && object_color.isValid()) {
outcolor = object_color;
return true;
}

Color4f basecol;
if (Renderer::getColorSchemeColor(colormode, basecol)) {
// In highlight/background mode, pull unset colors from the basecol
if (colormode == ColorMode::BACKGROUND || colormode != ColorMode::HIGHLIGHT) {
basecol = Color4f(object_color[0] >= 0 ? object_color[0] : basecol[0], object_color[1] >= 0 ? object_color[1] : basecol[1],
object_color[2] >= 0 ? object_color[2] : basecol[2], object_color[3] >= 0 ? object_color[3] : basecol[3]);
}
Color4f col;
Renderer::getColorSchemeColor(ColorMode::MATERIAL, col);
outcolor = basecol;
if (outcolor[0] < 0) outcolor[0] = col[0];
if (outcolor[1] < 0) outcolor[1] = col[1];
if (outcolor[2] < 0) outcolor[2] = col[2];
if (outcolor[3] < 0) outcolor[3] = col[3];
return true;
}

return false;
}



/* fill colormap_ with matching entries from the colorscheme. note
this does not change Highlight or Background colors as they are not
represented in the colorscheme (yet). Also edgecolors are currently the
Expand All @@ -176,7 +207,8 @@ std::vector<SelectedObject> Renderer::findModelObject(Vector3d near_pt, Vector3d
#else //NULLGL

Renderer::Renderer() : colorscheme_(nullptr) {}
bool Renderer::getColor(Renderer::ColorMode colormode, Color4f& col) const { return false; }
bool Renderer::getColorSchemeColor(Renderer::ColorMode colormode, Color4f& outcolor) const {return false; }
bool Renderer::getShaderColor(Renderer::ColorMode colormode, const Color4f& object_color, Color4f& outcolor) const { return false; }
std::string ShaderUtils::loadShaderSource(const std::string& name) { return ""; }
void Renderer::setColorScheme(const ColorScheme& cs) {}
std::vector<SelectedObject> Renderer::findModelObject(Vector3d near_pt, Vector3d far_pt, int mouse_x, int mouse_y, double tolerance) { return {}; }
Expand Down
3 changes: 2 additions & 1 deletion src/glview/Renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ class Renderer
EMPTY_SPACE
};

bool getColor(ColorMode colormode, Color4f& col) const;
bool getColorSchemeColor(ColorMode colormode, Color4f& outcolor) const;
bool getShaderColor(Renderer::ColorMode colormode, const Color4f& object_color, Color4f& outcolor) const;
virtual void setColorScheme(const ColorScheme& cs);

virtual std::vector<SelectedObject> findModelObject(Vector3d near_pt, Vector3d far_pt, int mouse_x, int mouse_y, double tolerance);
Expand Down
47 changes: 0 additions & 47 deletions src/glview/VBORenderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,33 +61,6 @@ void shader_attribs_disable(const ShaderUtils::ShaderInfo& shaderinfo)

VBORenderer::VBORenderer() : Renderer() {}

// TODO: Move to Renderer?
bool VBORenderer::getShaderColor(Renderer::ColorMode colormode, const Color4f& color,
Color4f& outcolor) const
{
if ((colormode != ColorMode::BACKGROUND) && (colormode != ColorMode::HIGHLIGHT) && color.isValid()) {
outcolor = color;
return true;
}
Color4f basecol;
if (Renderer::getColor(colormode, basecol)) {
if (colormode == ColorMode::BACKGROUND || colormode != ColorMode::HIGHLIGHT) {
basecol = Color4f(color[0] >= 0 ? color[0] : basecol[0], color[1] >= 0 ? color[1] : basecol[1],
color[2] >= 0 ? color[2] : basecol[2], color[3] >= 0 ? color[3] : basecol[3]);
}
Color4f col;
Renderer::getColor(ColorMode::MATERIAL, col);
outcolor = basecol;
if (outcolor[0] < 0) outcolor[0] = col[0];
if (outcolor[1] < 0) outcolor[1] = col[1];
if (outcolor[2] < 0) outcolor[2] = col[2];
if (outcolor[3] < 0) outcolor[3] = col[3];
return true;
}

return false;
}

size_t VBORenderer::calcNumVertices(const std::shared_ptr<CSGProducts>& products,
bool unique_geometry) const
{
Expand Down Expand Up @@ -193,23 +166,3 @@ void VBORenderer::add_shader_pointers(VBOBuilder& vbo_builder, const ShaderUtils

vbo_builder.states().emplace_back(std::move(ss));
}

// This will set the `color_area` and `color_edge` shader uniforms.
// ..meaning it will only be applicable to shaders using those uniforms, i.e. the edge shader
void VBORenderer::add_color(VBOBuilder& vbo_builder, const Color4f& color, const ShaderUtils::ShaderInfo *shaderinfo)
{
if (!shaderinfo) return;
add_shader_pointers(vbo_builder, shaderinfo);
std::shared_ptr<VertexState> color_state =
std::make_shared<VBOShaderVertexState>(0, 0, vbo_builder.verticesVBO(), vbo_builder.elementsVBO());
color_state->glBegin().emplace_back([shaderinfo, color]() {
GL_TRACE("glUniform4f(%d, %.2f, %.2f, %.2f, %.2f)", shaderinfo->uniforms.at("color_area") % color[0] % color[1] % color[2] % color[3]);
GL_CHECKD(
glUniform4f(shaderinfo->uniforms.at("color_area"), color[0], color[1], color[2], color[3]));
GL_TRACE("glUniform4f(%d, %.2f, %.2f, %.2f, %.2f)", shaderinfo->uniforms.at("color_edge") % ((color[0] + 1) / 2) % ((color[1] + 1) / 2) %
((color[2] + 1) / 2) % 1.0);
GL_CHECKD(glUniform4f(shaderinfo->uniforms.at("color_edge"), (color[0] + 1) / 2, (color[1] + 1) / 2,
(color[2] + 1) / 2, 1.0));
});
vbo_builder.states().emplace_back(std::move(color_state));
}
2 changes: 0 additions & 2 deletions src/glview/VBORenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,13 @@ class VBORenderer : public Renderer
{
public:
VBORenderer();
virtual bool getShaderColor(Renderer::ColorMode colormode, const Color4f& col, Color4f& outcolor) const;
virtual size_t calcNumVertices(const std::shared_ptr<CSGProducts>& products, bool unique_geometry = false) const;
virtual size_t calcNumVertices(const CSGChainObject& csgobj, bool unique_geometry = false) const;
virtual size_t calcNumVertices(const PolySet& polyset) const;
virtual size_t calcNumEdgeVertices(const PolySet& polyset) const;
virtual size_t calcNumEdgeVertices(const Polygon2d& polygon) const;

void add_shader_pointers(VBOBuilder& vbo_builder, const ShaderUtils::ShaderInfo *shaderinfo); // This could stay protected, were it not for VertexStateManager
void add_color(VBOBuilder& vbo_builder, const Color4f& color, const ShaderUtils::ShaderInfo *shaderinfo);

protected:
void add_shader_data(VBOBuilder& vbo_builder);
Expand Down
6 changes: 3 additions & 3 deletions src/glview/cgal/CGALRenderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ void CGALRenderer::createPolySetStates() {

for (const auto &polyset : this->polysets_) {
Color4f color;
getColor(ColorMode::MATERIAL, color);
getColorSchemeColor(ColorMode::MATERIAL, color);
vbo_builder.writeSurface();
vbo_builder.create_surface(*polyset, Transform3d::Identity(), color, false);
}
Expand Down Expand Up @@ -185,7 +185,7 @@ void CGALRenderer::createPolygonSurfaceStates() {

for (const auto &[polygon, polyset] : this->polygons_) {
Color4f color;
getColor(ColorMode::CGAL_FACE_2D_COLOR, color);
getColorSchemeColor(ColorMode::CGAL_FACE_2D_COLOR, color);
vbo_builder.create_polygons(*polyset, Transform3d::Identity(), color);
}

Expand Down Expand Up @@ -218,7 +218,7 @@ void CGALRenderer::createPolygonEdgeStates() {

for (const auto &[polygon, _] : this->polygons_) {
Color4f color;
getColor(ColorMode::CGAL_EDGE_2D_COLOR, color);
getColorSchemeColor(ColorMode::CGAL_EDGE_2D_COLOR, color);
vbo_builder.writeEdge();
vbo_builder.create_edges(*polygon, Transform3d::Identity(), color);
}
Expand Down
4 changes: 2 additions & 2 deletions src/glview/preview/OpenCSGRenderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ void OpenCSGRenderer::createCSGVBOProducts(
last_color = color;
}

add_color(vbo_builder, last_color, shaderinfo);
add_shader_pointers(vbo_builder, shaderinfo);

if (color[3] == 1.0f) {
// object is opaque, draw normally
Expand Down Expand Up @@ -297,7 +297,7 @@ void OpenCSGRenderer::createCSGVBOProducts(
last_color = color;
}

add_color(vbo_builder, last_color, shaderinfo);
add_shader_pointers(vbo_builder, shaderinfo);

// negative objects should only render rear faces
std::shared_ptr<VertexState> cull = std::make_shared<VertexState>();
Expand Down
6 changes: 3 additions & 3 deletions src/glview/preview/ThrownTogetherRenderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ void ThrownTogetherRenderer::createChainObject(VertexStateContainer& container,
const ColorMode colormode = getColorMode(csgobj.flags, highlight_mode, background_mode, false, type);
getShaderColor(colormode, leaf_color, color);

add_color(vbo_builder, color, shaderinfo);
add_shader_pointers(vbo_builder, shaderinfo);

vbo_builder.create_surface(*csgobj.leaf->polyset, csgobj.leaf->matrix, color, enable_barycentric);
if (const auto ttr_vs = std::dynamic_pointer_cast<TTRVertexState>(vbo_builder.states().back())) {
Expand All @@ -182,7 +182,7 @@ void ThrownTogetherRenderer::createChainObject(VertexStateContainer& container,
ColorMode colormode = getColorMode(csgobj.flags, highlight_mode, background_mode, false, type);
getShaderColor(colormode, leaf_color, color);

add_color(vbo_builder, color, shaderinfo);
add_shader_pointers(vbo_builder, shaderinfo);

auto cull = std::make_shared<VertexState>();
cull->glBegin().emplace_back([]() {
Expand All @@ -208,7 +208,7 @@ void ThrownTogetherRenderer::createChainObject(VertexStateContainer& container,
colormode = getColorMode(csgobj.flags, highlight_mode, background_mode, true, type);
getShaderColor(colormode, leaf_color, color);

add_color(vbo_builder, color, shaderinfo);
add_shader_pointers(vbo_builder, shaderinfo);

cull = std::make_shared<VertexState>();
cull->glBegin().emplace_back([]() {
Expand Down
10 changes: 9 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,7 @@ list(APPEND SCADFILES_WITH_COLOR
${TEST_SCAD_DIR}/3D/features/color-tests.scad
${TEST_SCAD_DIR}/3D/features/color-tests2.scad
${TEST_SCAD_DIR}/3D/features/color-tests3.scad
${TEST_SCAD_DIR}/3D/features/render-preserve-colors.scad
${TEST_SCAD_DIR}/3D/features/highlight-modifier.scad
${TEST_SCAD_DIR}/3D/features/linear_extrude-parameter-tests.scad
${TEST_SCAD_DIR}/3D/features/rotate-parameters.scad
Expand Down Expand Up @@ -900,6 +901,7 @@ list(APPEND SCADFILES_DIFFERENT_MANIFOLD_PREVIEW_EXPECTATIONS
# render() in manifold mode preserves colors
${TEST_SCAD_DIR}/3D/features/render-tests.scad
${TEST_SCAD_DIR}/misc/internal-cavity.scad
${TEST_SCAD_DIR}/3D/features/render-preserve-colors.scad

# resize() in manifold mode preserves colors
${TEST_SCAD_DIR}/3D/features/resize-convexity-tests.scad
Expand Down Expand Up @@ -1350,9 +1352,14 @@ add_cmdline_test(openscad-camvp-override OPENSCAD FILES ${CAMERA_TEST_VP} S
set(VIEW_OPTIONS_TEST "${TEST_SCAD_DIR}/3D/misc/view-options-tests.scad")
add_cmdline_test(openscad-viewoptions-axes OPENSCAD FILES ${VIEW_OPTIONS_TEST} SUFFIX png ARGS ${IMGSIZE} --camera=80,14,19,0,0,0 --viewall --view axes)
add_cmdline_test(openscad-viewoptions-axes-scales OPENSCAD FILES ${VIEW_OPTIONS_TEST} SUFFIX png ARGS ${IMGSIZE} --camera=80,14,19,0,0,0 --viewall --view axes,scales)
add_cmdline_test(openscad-viewoptions-edges OPENSCAD FILES ${VIEW_OPTIONS_TEST} SUFFIX png ARGS ${IMGSIZE} --camera=80,14,19,0,0,0 --viewall --view edges)
add_cmdline_test(openscad-viewoptions-axes-scales-edges OPENSCAD FILES ${VIEW_OPTIONS_TEST} SUFFIX png ARGS ${IMGSIZE} --camera=80,14,19,0,0,0 --viewall --view axes,scales,edges)
add_cmdline_test(openscad-viewoptions-crosshairs OPENSCAD FILES ${VIEW_OPTIONS_TEST} SUFFIX png ARGS ${IMGSIZE} --camera=80,14,19,0,0,0 --viewall --render --view crosshairs)
set(VIEW_OPTIONS_EDGES_TEST
${VIEW_OPTIONS_TEST}
${TEST_SCAD_DIR}/3D/features/render-preserve-colors.scad
)
add_cmdline_test(openscad-viewoptions-edges OPENSCAD FILES ${VIEW_OPTIONS_EDGES_TEST} SUFFIX png ARGS ${IMGSIZE} --camera=80,14,19,0,0,0 --viewall --view edges)
add_cmdline_test(openscad-manifold-viewoptions-edges OPENSCAD FILES ${VIEW_OPTIONS_EDGES_TEST} SUFFIX png ARGS ${IMGSIZE} --camera=80,14,19,0,0,0 --viewall --view edges --backend=manifold)

#
# Colorscheme tests
Expand Down Expand Up @@ -1509,6 +1516,7 @@ set_tests_properties(
# OpenCSG z fighting https://github.com/openscad/openscad/issues/4595
openscad-viewoptions-edges_view-options-tests
openscad-viewoptions-axes-scales-edges_view-options-tests
openscad-manifold-viewoptions-edges_view-options-tests
previewtest_surface_image
throwntogethertest_surface_image

Expand Down
8 changes: 8 additions & 0 deletions tests/data/scad/3D/features/render-preserve-colors.scad
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
render() difference() {
union() {
color("red") cube(10);
color("green") translate([20,0,0]) cube(10);
}
color("blue") translate([-1,-5,5]) cube([32,10,10]);
}
color("purple") translate([-1,-1,-1]) cube([32,12,2]);
25 changes: 25 additions & 0 deletions tests/regression/dumptest/render-preserve-colors-expected.csg
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
render(convexity = 1) {
difference() {
union() {
color([1, 0, 0, 1]) {
cube(size = [10, 10, 10], center = false);
}
color([0, 0.501961, 0, 1]) {
multmatrix([[1, 0, 0, 20], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [10, 10, 10], center = false);
}
}
}
color([0, 0, 1, 1]) {
multmatrix([[1, 0, 0, -1], [0, 1, 0, -5], [0, 0, 1, 5], [0, 0, 0, 1]]) {
cube(size = [32, 10, 10], center = false);
}
}
}
}
color([0.501961, 0, 0.501961, 1]) {
multmatrix([[1, 0, 0, -1], [0, 1, 0, -1], [0, 0, 1, -1], [0, 0, 0, 1]]) {
cube(size = [32, 12, 2], center = false);
}
}

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 5d7b26f

Please sign in to comment.