如何将每个图元的中心坐标传递给片段着色器?
问题描述
我想用SFML手动创建包含(x, y, angle)的点,然后在每个点周围绘制圆形。目前angle仅用于调试,后续会正式使用。
实现步骤:
- SFML绘制点
- 顶点着色器将点坐标转换到-1..1范围
- 几何着色器在每个点位置生成正方形,并把中心坐标传递给片段着色器
- 片段着色器在每个正方形内绘制圆形
我的思路是在几何着色器中输出每个图元的中心坐标center,通过计算片段到该中心的距离,就能在片段着色器里为每个图元绘制圆形。但实际运行后发现center似乎只被设置了一次,导致渲染效果异常(如图)。

SFML应用代码
#include <iostream> #include <SFML/Graphics.hpp> #include <vector> #include <GL/glew.h> #include <random> #define WIDTH 800 int main() { sf::RenderWindow window(sf::VideoMode(WIDTH, WIDTH), "Test"); sf::Shader shader; shader.loadFromFile("shader.vert", "shader.geom", "shader.frag"); sf::Transform matrix = sf::Transform::Identity; matrix.scale(1.0 / WIDTH, 1.0 / WIDTH); sf::Glsl::Mat4 projectionViewMatrix = matrix; shader.setUniform("projectionViewMatrix", projectionViewMatrix); std::vector<GLfloat> vertices; vertices.push_back(400.0); vertices.push_back(400.0); vertices.push_back(0.0); vertices.push_back(400.0); vertices.push_back(-400.0); vertices.push_back(0.25); vertices.push_back(-400.0); vertices.push_back(-400.0); vertices.push_back(0.5); vertices.push_back(-400.0); vertices.push_back(400.0); vertices.push_back(0.75); while (window.isOpen()) { sf::Event currEvent; while (window.pollEvent(currEvent)) { switch (currEvent.type) { case(sf::Event::Closed): window.close(); break; } } window.clear(sf::Color::Black); glVertexPointer(3, GL_FLOAT, 0, vertices.data()); glEnableClientState(GL_VERTEX_ARRAY); glDrawArrays(GL_POINTS, 0, vertices.size() / 3); glDisableClientState(GL_VERTEX_ARRAY); sf::Shader::bind(&shader); window.display(); } }
顶点着色器(shader.vert)
#version 150 in vec3 position; out vec3 pass_colour; out float angle; uniform mat4 projectionViewMatrix; void main(void) { gl_Position = projectionViewMatrix * vec4(position.xy, 0.0 ,1.0); angle = position.z; pass_colour = vec3(1.0); }
几何着色器(shader.geom)
#version 150 layout (points) in; layout (triangle_strip, max_vertices = 6) out; in vec3 pass_colour[]; in float angle[]; out vec3 finalColour; out vec4 centerPosition; uniform mat4 projectionViewMatrix; vec3 hsv2rgb(vec3 c) { vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); } void createVertex(vec3 offset, vec3 colour, float z = 0.0) { vec4 actualOffset = vec4(offset, z); vec4 worldPosition = gl_in[0].gl_Position + actualOffset; gl_Position = worldPosition; finalColour = colour; vec4 pointPosition = gl_in[0].gl_Position; centerPosition = pointPosition; EmitVertex(); } void main(void) { float corner = 0.3; vec3 colour = hsv2rgb(vec3(angle[0], 1.0, 1.0)); createVertex(vec3(-corner, -corner, 0.0), colour, 0.0); createVertex(vec3(corner, -corner, 0.0), colour, 0.0); createVertex(vec3(-corner, corner, 0.0), colour, 0.0); createVertex(vec3(corner, corner, 0.0), colour, 0.0); createVertex(vec3(corner, -corner, 0.0), colour, 0.0); createVertex(vec3(-corner, corner, 0.0), colour, 0.0); EndPrimitive(); }
片段着色器(shader.frag)
#version 150 in vec3 finalColour; in vec4 centerPosition; out vec4 out_Colour; void main(void){ vec2 resolution = vec2(800.0/2.0, 800.0/2.0); vec2 uv = gl_FragCoord.xy / resolution.xy; vec2 uvc = (centerPosition.xy + vec2(1.0)) / 2.0; float dist = length(uv - uvc); out_Colour = vec4(finalColour * dist, 0.8); }
内容的提问来源于stack exchange,提问作者nowox
相关产品推荐
相关产品推荐

