(请参见最后的更新以获取针对我的特定情况的解决方案...在此问题更简洁地给出,并且解决方案在此问题中更彻底地涵盖:Cannot cast array to pointer)
我成功运行了第一个示例(蓝色三角形),然后将其从C ++重构为C99,同样成功。我基于此C版本开始了一个新项目,该项目通过算法生成点,但在功能上与仍在运行的示例相同,并且在不同的执行之间渲染的图像不一致。
该程序应该在屏幕的上半部分绘制一个蓝色的抛物线,但是在空的黑框和从中心到窗口左中点或右中点的水平线之间变化。
我开始做事时有所不同,更“正确”,例如不使用全局变量,或者在我看来像枚举的滥用(NumVAO,NumBuffers),但是由于事情没有如我预期的那样,我做了更多更改,更多与示例代码匹配的代码。使用-std=c99 -Wall -pedantic
可以正常编译所有文件,并且无论静态还是动态链接glew和freeglut,结果都是相同的。
我真的看不出有什么问题。我验证了抛物线函数返回的结果正确,并且数据的格式与书中所述的相同。由于结果不一致,我怀疑这可能与malloc不能清除顶点数组的内存有关,但是使用calloc可以得到相同的结果。似乎屏幕坐标运行不正常,我无法想象为什么。
完整资料位于
https://github.com/markmccormack/concentrator
我相当确定问题出在我的抛物线代码上,因为这是唯一的实际区别,所以这里是相关的部分:
/* parabola.h
* generate parabolas in the form y = ax^2
* return a compact set of 2D points describing it
*/
#ifndef __PARABOLA_H__
#define __PARABOLA_H__
#include <GL/glew.h>
GLfloat**
v_parabola_by_a ( GLfloat a, GLuint num_points ) ;
#endif /* __PARABOLA_H__ */
和实现:
#include <stdio.h>
#include <stdlib.h>
#include "parabola.h"
GLfloat**
v_parabola_by_a ( GLfloat a, GLuint num_points ) {
/* Array of X and Y values */
GLfloat **points ;
points = calloc( num_points, sizeof(GLfloat[2]) ) ;
if( points == NULL ) {
fprintf( stderr, "Could not allocate memory, exiting.\n" ) ;
exit(EXIT_FAILURE) ;
} else {
int iter_alloc ;
for( iter_alloc = 0; iter_alloc <= num_points; iter_alloc++ ) {
points[iter_alloc] = calloc( 2, sizeof(GLfloat) ) ;
}
}
/* Each point is incremented along x by 'inc_x,' for a -1,+1 range */
GLfloat inc_x = 2.0 / (float)num_points ;
int iter_point ;
for (iter_point = 0; iter_point <= num_points; iter_point++ ) {
GLfloat x_value = (GLfloat)iter_point * inc_x - 1.0 ;
GLfloat y_value = x_value * x_value * a ; /* y = a x^2 */
points[iter_point][0] = x_value ;
points[iter_point][1] = y_value ;
}
return points ;
}
GLfloat **数组像这样传递给OpenGL:
GLfloat **points ;
points = calloc( num_points, sizeof(GLfloat[2]) ) ;
if( points == NULL ) {
fprintf( stdout, "Could not allocate memory.\n" ) ;
exit( EXIT_FAILURE ) ;
} else {
int iter_alloc ;
for( iter_alloc = 0; iter_alloc <= num_points; iter_alloc++ ) {
points[iter_alloc] = calloc( 2, sizeof(GLfloat) ) ;
}
}
points = v_parabola_by_a( 1.0, num_points ) ;
/* Create & bind renderable asset */
glGenVertexArrays( NumVAOs, VAOs ) ;
glBindVertexArray( VAOs[Parabola] ) ;
/* Create & bind vertex array */
glGenBuffers( NumBuffers, Buffers ) ;
glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer] ) ;
/* Populate bound vertex array with the asset */
glBufferData( GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW ) ;
任何帮助或建议,不胜感激!
我遇到的核心问题是我缺乏对指针与数组的关系的理解,错误地假设在这种情况下两者可以互换使用。具体来说,使用像n-D数组这样的指针数组是不正确的,并且虽然可以通过这种方式存储数据,但在将其作为内存块传递之前,必须将其展开为平面数组。这些是修复程序的更改:
顶点数组从
GLfloat**
更改为GLfloat*
glBufferData的大小参数已从
sizeof(points)
更改为num_points*2*sizeof(GLfloat)
用
GLfloat** v_parabola_by_a( float a, int num_points ) ;
代替void v_parabola_by_a( float a, int num_points, GLfloat* output) ;
将生成顶点数组的函数从memcpy(output, points, num_points*2*sizeof(GLfloat))
更改为return(points)
,从而更正了指针的多重分配。严格来说,这不是建议的做法,但我认为这是可行的解决方案。
最佳答案
glBufferData( GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW ) ;
错了
glBufferData
需要平面数组,而不是浮点数组的指针数组。同样,sizeof(points)
只是一个指针的大小,而不是数组的大小。分配2个浮点数的数组没有意义。创建一个可以容纳所有数据的大数组,并将其填充[0] = first_x,[1] = first_y,[2] = second_x,...
关于c - OpenGL:C语言改编的红皮书示例中的不稳定渲染,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22784735/