cocoa - support - opengl standard
El proyecto de cacao 3.2 más simple, minimalista y abierto (2)
Aquí hay una respuesta basada en el código en https://github.com/beelsebob/Cocoa-GL-Tutorial . Cambié estas cosas: (1) El contexto de OpenGL se crea en un NSOpenGLView personalizado y no se agrega directamente a la ventana. (2) I toda la inicialización en una sola función. (3) Eliminé todo el código de verificación de error. Esto no es algo que deba hacer por un producto, pero me resulta más fácil entender el código con menos desorden ... (mire en Cocoa-GL-Tutorial para un correcto manejo de errores).
Los pasos (probados con Xcode 5.1):
- Hacer una nueva aplicación de cacao
- Agregar una vista personalizada a la ventana de la aplicación en el constructor de interfaz
- Agregue una clase Objective-C, subclassing NSOpenGLView, lo llamé MyOpenGLView
- En el constructor de interfaz, seleccione CustomView, seleccione el Inspector de identidad (uno de los iconos arriba a la derecha) y en Custom Class seleccione MyOpenGLView
- Ahora, este es el código para
MyOpenGLView.h
:
#import <Cocoa/Cocoa.h> #import <OpenGL/OpenGL.h> #import <OpenGL/gl3.h> @interface MyOpenGLView : NSOpenGLView { GLuint shaderProgram; GLuint vertexArrayObject; GLuint vertexBuffer; GLint positionUniform; GLint colourAttribute; GLint positionAttribute; } @end
Y este es el código para MyOpenGLView.m
:
#import "MyOpenGLView.h" @implementation MyOpenGLView - (id)initWithFrame:(NSRect)frame { // 1. Create a context with opengl pixel format NSOpenGLPixelFormatAttribute pixelFormatAttributes[] = { NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, NSOpenGLPFAColorSize , 24 , NSOpenGLPFAAlphaSize , 8 , NSOpenGLPFADoubleBuffer , NSOpenGLPFAAccelerated , NSOpenGLPFANoRecovery , 0 }; NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttributes]; self = [super initWithFrame:frame pixelFormat:pixelFormat]; // 2. Make the context current [[self openGLContext] makeCurrentContext]; // 3. Define and compile vertex and fragment shaders GLuint vs; GLuint fs; const char *vss="#version 150/n/ uniform vec2 p;/ in vec4 position;/ in vec4 colour;/ out vec4 colourV;/ void main (void)/ {/ colourV = colour;/ gl_Position = vec4(p, 0.0, 0.0) + position;/ }"; const char *fss="#version 150/n/ in vec4 colourV;/ out vec4 fragColour;/ void main(void)/ {/ fragColour = colourV;/ }"; vs = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vs, 1, &vss, NULL); glCompileShader(vs); fs = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fs, 1, &fss, NULL); glCompileShader(fs); printf("vs: %i, fs: %i/n",vs,fs); // 4. Attach the shaders shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vs); glAttachShader(shaderProgram, fs); glBindFragDataLocation(shaderProgram, 0, "fragColour"); glLinkProgram(shaderProgram); // 5. Get pointers to uniforms and attributes positionUniform = glGetUniformLocation(shaderProgram, "p"); colourAttribute = glGetAttribLocation(shaderProgram, "colour"); positionAttribute = glGetAttribLocation(shaderProgram, "position"); glDeleteShader(vs); glDeleteShader(fs); printf("positionUniform: %i, colourAttribute: %i, positionAttribute: %i/n",positionUniform,colourAttribute,positionAttribute); // 6. Upload vertices (1st four values in a row) and colours (following four values) GLfloat vertexData[]= { -0.5,-0.5,0.0,1.0, 1.0,0.0,0.0,1.0, -0.5, 0.5,0.0,1.0, 0.0,1.0,0.0,1.0, 0.5, 0.5,0.0,1.0, 0.0,0.0,1.0,1.0, 0.5,-0.5,0.0,1.0, 1.0,1.0,1.0,1.0}; glGenVertexArrays(1, &vertexArrayObject); glBindVertexArray(vertexArrayObject); glGenBuffers(1, &vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); glBufferData(GL_ARRAY_BUFFER, 4*8*sizeof(GLfloat), vertexData, GL_STATIC_DRAW); glEnableVertexAttribArray((GLuint)positionAttribute); glEnableVertexAttribArray((GLuint)colourAttribute ); glVertexAttribPointer((GLuint)positionAttribute, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), 0); glVertexAttribPointer((GLuint)colourAttribute , 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (char*)0+4*sizeof(GLfloat)); return self; } - (void)drawRect:(NSRect)dirtyRect { [super drawRect:dirtyRect]; glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(shaderProgram); GLfloat p[]={0,0}; glUniform2fv(positionUniform, 1, (const GLfloat *)&p); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); [[self openGLContext] flushBuffer]; } @end
He usado el legado OpenGL con Cocoa durante años, pero ahora estoy luchando para hacer la transición a OpenGL 3.2. Hay varios ejemplos en Internet, pero son demasiado complejos (y muchos ni siquiera compilan en XCode 5.1). ¿Podría alguien escribir un ejemplo del código de cacao mínimo más simple, minimalista para dibujar un triángulo de lectura en un NSOpenGLView? (sin shaders sofisticados, sin displayCallbacks, cuanto menos las líneas de código, mejor).
https://.com/a/22502999/4946861
En xcode 6.3.2 obtuve el ejemplo ejecutando afterreplacement de
(id)initWithFrame:(NSRect)frame
con
(void)awakeFromNib
y reemplazo de
self = [super initWithFrame:frame pixelFormat:pixelFormat];
con
super.pixelFormat=pixelFormat;
y eliminación de
return self;
o escrito en detalle:
#import "MyOpenGLView.h"
@implementation MyOpenGLView
- (void)awakeFromNib
{
NSLog(@"...was here");
// 1. Create a context with opengl pixel format
NSOpenGLPixelFormatAttribute pixelFormatAttributes[] =
{
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
NSOpenGLPFAColorSize , 24 ,
NSOpenGLPFAAlphaSize , 8 ,
NSOpenGLPFADoubleBuffer ,
NSOpenGLPFAAccelerated ,
NSOpenGLPFANoRecovery ,
0
};
NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttributes];
super.pixelFormat=pixelFormat;
// 2. Make the context current
[[self openGLContext] makeCurrentContext];
// 3. Define and compile vertex and fragment shaders
GLuint vs;
GLuint fs;
const char *vss="#version 150/n/
uniform vec2 p;/
in vec4 position;/
in vec4 colour;/
out vec4 colourV;/
void main (void)/
{/
colourV = colour;/
gl_Position = vec4(p, 0.0, 0.0) + position;/
}";
const char *fss="#version 150/n/
in vec4 colourV;/
out vec4 fragColour;/
void main(void)/
{/
fragColour = colourV;/
}";
vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vss, NULL);
glCompileShader(vs);
fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fss, NULL);
glCompileShader(fs);
printf("vs: %i, fs: %i/n",vs,fs);
// 4. Attach the shaders
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vs);
glAttachShader(shaderProgram, fs);
glBindFragDataLocation(shaderProgram, 0, "fragColour");
glLinkProgram(shaderProgram);
// 5. Get pointers to uniforms and attributes
positionUniform = glGetUniformLocation(shaderProgram, "p");
colourAttribute = glGetAttribLocation(shaderProgram, "colour");
positionAttribute = glGetAttribLocation(shaderProgram, "position");
glDeleteShader(vs);
glDeleteShader(fs);
printf("positionUniform: %i, colourAttribute: %i, positionAttribute: %i/n",positionUniform,colourAttribute,positionAttribute);
// 6. Upload vertices (1st four values in a row) and colours (following four values)
GLfloat vertexData[]= { -0.5,-0.5,0.0,1.0, 1.0,0.0,0.0,1.0,
-0.5, 0.5,0.0,1.0, 0.0,1.0,0.0,1.0,
0.5, 0.5,0.0,1.0, 0.0,0.0,1.0,1.0,
0.5,-0.5,0.0,1.0, 1.0,1.0,1.0,1.0};
glGenVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 4*8*sizeof(GLfloat), vertexData, GL_STATIC_DRAW);
glEnableVertexAttribArray((GLuint)positionAttribute);
glEnableVertexAttribArray((GLuint)colourAttribute );
glVertexAttribPointer((GLuint)positionAttribute, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), 0);
glVertexAttribPointer((GLuint)colourAttribute , 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (char*)0+4*sizeof(GLfloat));
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// Drawing code here.
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
GLfloat p[]={0,0};
glUniform2fv(positionUniform, 1, (const GLfloat *)&p);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
[[self openGLContext] flushBuffer];
}
@end