如何用OpenGL绘制移动函数图?
Posted
技术标签:
【中文标题】如何用OpenGL绘制移动函数图?【英文标题】:How to draw a moving function graph with OpenGl? 【发布时间】:2013-05-11 22:06:15 【问题描述】:我正在使用 OpenGL 来制作一个看起来像这样的图形:
这是我目前得到的代码:
void GLWidget::paintGL()
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0,1,0); //Green
// Frequency Line
glLineWidth(3.0);
glBegin(GL_LINE_STRIP);
glVertex2f(-1,0);
glVertex2f(x1,y1);
glEnd();
y1 = randVarGen();
x1 = randVarGen();
我有一个计时器,每 50 毫秒重绘一次图表。我想从一条直线开始,并基于音频文件中的变量(我现在使用随机变量),图表应该像音乐可视化器一样上下波动。
【问题讨论】:
你的问题是什么? 嘿抱歉我不清楚。使用我现在拥有的代码,一端保持静止,另一端疯狂跳跃。有没有一种方法可以使两端静止但中间随 randVars 而变化? 我相信你需要更多的积分。 例如在glBegin/glEnd中创建一个循环并多次调用glVertex2f来添加更多点。 你能分享这个图的源代码吗?它可能对某些人有用。 【参考方案1】:您需要对要绘制的函数进行采样。
glBegin(GL_LINE_STRIP);
glVertex2f(0f, 0f);
for (float x = 1f; x < 100f; x += 1f)
glVertex2f(x, randVarGen());
glVertex2f(100f, 0f);
glEnd();
【讨论】:
【参考方案2】:Wikibooks OpenGL 教程示例
在 Ubuntu 16.04 上测试。
https://en.wikibooks.org/wiki/OpenGL_Programming/Scientific_OpenGL_Tutorial_01 https://gitlab.com/wikibooks-opengl/modern-tutorials/tree/2d8a441d8db81b4a619cf583769d1ea1451f4529/graph01该仓库的关键文件是:
图形.cpp
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glew.h>
#include <GL/glut.h>
#include "../common/shader_utils.h"
#include "res_texture.c"
GLuint program;
GLint attribute_coord2d;
GLint uniform_offset_x;
GLint uniform_scale_x;
GLint uniform_sprite;
GLuint texture_id;
GLint uniform_mytexture;
float offset_x = 0.0;
float scale_x = 1.0;
int mode = 0;
struct point
GLfloat x;
GLfloat y;
;
GLuint vbo;
int init_resources()
program = create_program("graph.v.glsl", "graph.f.glsl");
if (program == 0)
return 0;
attribute_coord2d = get_attrib(program, "coord2d");
uniform_offset_x = get_uniform(program, "offset_x");
uniform_scale_x = get_uniform(program, "scale_x");
uniform_sprite = get_uniform(program, "sprite");
uniform_mytexture = get_uniform(program, "mytexture");
if (attribute_coord2d == -1 || uniform_offset_x == -1 || uniform_scale_x == -1 || uniform_sprite == -1 || uniform_mytexture == -1)
return 0;
/* Enable blending */
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/* Enable point sprites (not necessary for true OpenGL ES 2.0) */
#ifndef GL_ES_VERSION_2_0
glEnable(GL_POINT_SPRITE);
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
#endif
/* Upload the texture for our point sprites */
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, res_texture.width, res_texture.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, res_texture.pixel_data);
// Create the vertex buffer object
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// Create our own temporary buffer
point graph[2000];
// Fill it in just like an array
for (int i = 0; i < 2000; i++)
float x = (i - 1000.0) / 100.0;
graph[i].x = x;
graph[i].y = sin(x * 10.0) / (1.0 + x * x);
// Tell OpenGL to copy our array to the buffer object
glBufferData(GL_ARRAY_BUFFER, sizeof graph, graph, GL_STATIC_DRAW);
return 1;
void display()
glUseProgram(program);
glUniform1i(uniform_mytexture, 0);
glUniform1f(uniform_offset_x, offset_x);
glUniform1f(uniform_scale_x, scale_x);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
/* Draw using the vertices in our vertex buffer object */
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(attribute_coord2d);
glVertexAttribPointer(attribute_coord2d, 2, GL_FLOAT, GL_FALSE, 0, 0);
/* Push each element in buffer_vertices to the vertex shader */
switch (mode)
case 0:
glUniform1f(uniform_sprite, 0);
glDrawArrays(GL_LINE_STRIP, 0, 2000);
break;
case 1:
glUniform1f(uniform_sprite, 1);
glDrawArrays(GL_POINTS, 0, 2000);
break;
case 2:
glUniform1f(uniform_sprite, res_texture.width);
glDrawArrays(GL_POINTS, 0, 2000);
break;
glutSwapBuffers();
void special(int key, int x, int y)
switch (key)
case GLUT_KEY_F1:
mode = 0;
printf("Now drawing using lines.\n");
break;
case GLUT_KEY_F2:
mode = 1;
printf("Now drawing using points.\n");
break;
case GLUT_KEY_F3:
mode = 2;
printf("Now drawing using point sprites.\n");
break;
case GLUT_KEY_LEFT:
offset_x -= 0.1;
break;
case GLUT_KEY_RIGHT:
offset_x += 0.1;
break;
case GLUT_KEY_UP:
scale_x *= 1.5;
break;
case GLUT_KEY_DOWN:
scale_x /= 1.5;
break;
case GLUT_KEY_HOME:
offset_x = 0.0;
scale_x = 1.0;
break;
glutPostRedisplay();
void free_resources()
glDeleteProgram(program);
int main(int argc, char *argv[])
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize(640, 480);
glutCreateWindow("My Graph");
GLenum glew_status = glewInit();
if (GLEW_OK != glew_status)
fprintf(stderr, "Error: %s\n", glewGetErrorString(glew_status));
return 1;
if (!GLEW_VERSION_2_0)
fprintf(stderr, "No support for OpenGL 2.0 found\n");
return 1;
GLfloat range[2];
glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, range);
if (range[1] < res_texture.width)
fprintf(stderr, "WARNING: point sprite range (%f, %f) too small\n", range[0], range[1]);
printf("Use left/right to move horizontally.\n");
printf("Use up/down to change the horizontal scale.\n");
printf("Press home to reset the position and scale.\n");
printf("Press F1 to draw lines.\n");
printf("Press F2 to draw points.\n");
printf("Press F3 to draw point sprites.\n");
if (init_resources())
glutDisplayFunc(display);
glutSpecialFunc(special);
glutMainLoop();
free_resources();
return 0;
graph.f.glsl
uniform sampler2D mytexture;
varying vec4 f_color;
uniform float sprite;
void main(void)
if (sprite > 1.0)
gl_FragColor = texture2D(mytexture, gl_PointCoord) * f_color;
else
gl_FragColor = f_color;
graph.v.glsl
attribute vec2 coord2d;
varying vec4 f_color;
uniform float offset_x;
uniform float scale_x;
uniform lowp float sprite;
void main(void)
gl_Position = vec4((coord2d.x + offset_x) * scale_x, coord2d.y, 0, 1);
f_color = vec4(coord2d.xy / 2.0 + 0.5, 1, 1);
gl_PointSize = max(1.0, sprite);
【讨论】:
感谢有用的参考代码,但读者应该注意,这个答案缺少一些文件并且不会按原样编译,你最好克隆整个 gitlab repo。 (另外,仅供参考,此复制/粘贴是合法的,因为链接的代码和文章是在公共领域/WTFPL 下发布的)。以上是关于如何用OpenGL绘制移动函数图?的主要内容,如果未能解决你的问题,请参考以下文章
如何用OpenGL的点精灵(point sprite)绘制雪花?
android opengl GLES20:如何用每个模型矩阵绘制多个三角形? (表现不错))