本文主要是介绍OpenGL绘制多边形边框线,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
利用OpenGL如何在绘制多边形的时候同时绘制其变现呢?
网上一种解决方案是利用glPolygonMode,将多边形绘制两次,一次绘制面,一次绘制边。这种方案理论上是可行的(我没有试过),但是OpenGL要进行两次绘制,效率上明显是不高的。
如果以顺时针绘制则是反面,逆时针绘制则是正面
// 设置正面为填充模式
glPolygonMode(GL_FRONT, GL_FILL);
// 设置反面为线形模式
glPolygonMode(GL_BACK, GL_LINE);
// 设置逆时针绘制一个正方形
参考了Easy wireframe display with barycentric coordinates这篇博文,参考其方法,使用Barycentric Coordinates(重心坐标),在GLSL中直接进行判断,如果离边近的像素就渲染成别的颜色。
要注意的主要有两点:
1. 在定点坐标数组中增加一个重心坐标属性,如下图。
2. 在GLSL中对重心坐标进行判断。
参考代码如下:
(使用了GLEW、SFML和GLM第三方库)
#include <GL/glew.h>
#include <SFML/Window.hpp>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>// Shader sources
const GLchar* vertexSource ="#version 150 core\n""varying vec3 vBC;""attribute vec3 position;""attribute vec3 barycentric;""uniform mat4 model;""uniform mat4 view;""uniform mat4 proj;""void main() {"" vBC = barycentric;"" gl_Position = proj * view * model * vec4(position, 1.0);""}";
const GLchar* fragmentSource ="#version 150 core\n""varying vec3 vBC;""void main() {"" if(any(lessThan(vBC, vec3(0.005)))){"" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);"" }"" else{"" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);"" }""}";int main()
{sf::ContextSettings settings;settings.depthBits = 24;settings.stencilBits = 8;sf::Window window(sf::VideoMode(800, 600, 32), "OpenGL", sf::Style::Titlebar | sf::Style::Close, settings);// Initialize GLEWglewExperimental = GL_TRUE;glewInit();glEnable(GL_DEPTH_TEST);// Create Vertex Array ObjectGLuint vao;glGenVertexArrays(1, &vao);glBindVertexArray(vao);// Create a Vertex Buffer Object and copy the vertex data to itGLuint vbo;glGenBuffers(1, &vbo);GLfloat vertices[] = {// 三维定点坐标 //重心坐标-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f,0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f,-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f};glBindBuffer(GL_ARRAY_BUFFER, vbo);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);// Create and compile the vertex shaderGLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader, 1, &vertexSource, NULL);glCompileShader(vertexShader);// Create and compile the fragment shaderGLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentSource, NULL);glCompileShader(fragmentShader);// Link the vertex and fragment shader into a shader programGLuint shaderProgram = glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);glUseProgram(shaderProgram);// Specify the layout of the vertex dataGLint posAttrib = glGetAttribLocation(shaderProgram, "position");glEnableVertexAttribArray(posAttrib);glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), 0);GLint baryAttrib = glGetAttribLocation(shaderProgram, "barycentric");glEnableVertexAttribArray(baryAttrib);glVertexAttribPointer(baryAttrib, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));// Set up projectionglm::mat4 view = glm::lookAt(glm::vec3(1.5f, 1.5f, 1.5f),glm::vec3(0.0f, 0.0f, 0.0f),glm::vec3(0.0f, 0.0f, 1.0f));GLint uniView = glGetUniformLocation(shaderProgram, "view");glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view));glm::mat4 proj = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 1.0f, 10.0f);GLint uniProj = glGetUniformLocation(shaderProgram, "proj");glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(proj));glm::mat4 model;GLint uniModel = glGetUniformLocation(shaderProgram, "model");model = glm::rotate(model, glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f));glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));while (window.isOpen()){sf::Event windowEvent;while (window.pollEvent(windowEvent)){switch (windowEvent.type){case sf::Event::Closed:window.close();break;}}// Clear the screen to blackglClearColor(0.0f, 0.0f, 0.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Draw cubeglDrawArrays(GL_TRIANGLES, 0, 36);// Swap bufferswindow.display();}glDeleteProgram(shaderProgram);glDeleteShader(fragmentShader);glDeleteShader(vertexShader);glDeleteBuffers(1, &vbo);glDeleteVertexArrays(1, &vao);return EXIT_SUCCESS;
}
最后的渲染效果如下:
如图渲染效果不是很好,有明显的锯齿。如何反锯齿,参看原始博文Easy wireframe display with barycentric coordinates。
这篇关于OpenGL绘制多边形边框线的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!