framework2
2019 строк · 63.8 Кб
1#include "ofGLRenderer.h"
2#include "ofMesh.h"
3#include "ofPath.h"
4#include "of3dPrimitives.h"
5#include "ofBitmapFont.h"
6#include "ofGLUtils.h"
7#include "ofImage.h"
8#include "ofFbo.h"
9#include "ofLight.h"
10#include "ofCamera.h"
11#include "ofTrueTypeFont.h"
12#include "ofNode.h"
13#include "ofVideoBaseTypes.h"
14#include "ofMaterial.h"
15#include "ofVboMesh.h"
16
17using std::shared_ptr;
18using std::vector;
19using std::string;
20
21const std::string ofGLRenderer::TYPE="GL";
22
23//----------------------------------------------------------
24ofGLRenderer::ofGLRenderer(const ofAppBaseWindow * _window)
25:matrixStack(_window)
26,graphics3d(this){
27bBackgroundAuto = true;
28
29linePoints.resize(2);
30rectPoints.resize(4);
31triPoints.resize(3);
32normalsEnabled = false;
33lightingEnabled = false;
34materialBound = false;
35alphaMaskTextureTarget = GL_TEXTURE_2D;
36window = _window;
37currentFramebufferId = 0;
38defaultFramebufferId = 0;
39path.setMode(ofPath::POLYLINES);
40path.setUseShapeColor(false);
41}
42
43void ofGLRenderer::setup(){
44#ifdef TARGET_OPENGLES
45// OpenGL ES might have set a default frame buffer for
46// MSAA rendering to the window, bypassing ofFbo, so we
47// can't trust ofFbo to have correctly tracked the bind
48// state. Therefore, we are forced to use the slower glGet() method
49// to be sure to get the correct default framebuffer.
50GLint currentFrameBuffer;
51glGetIntegerv(GL_FRAMEBUFFER_BINDING, ¤tFrameBuffer);
52defaultFramebufferId = currentFrameBuffer;
53currentFramebufferId = defaultFramebufferId;
54#endif
55setupGraphicDefaults();
56viewport();
57setupScreenPerspective();
58}
59
60void ofGLRenderer::startRender(){
61currentFramebufferId = defaultFramebufferId;
62framebufferIdStack.push_back(defaultFramebufferId);
63matrixStack.setRenderSurface(*window);
64viewport();
65// to do non auto clear on PC for now - we do something like "single" buffering --
66// it's not that pretty but it work for the most part
67
68#ifdef TARGET_WIN32
69if (getBackgroundAuto() == false){
70glDrawBuffer (GL_FRONT);
71}
72#endif
73
74if ( getBackgroundAuto() ){// || ofGetFrameNum() < 3){
75background(currentStyle.bgColor);
76}
77}
78
79void ofGLRenderer::finishRender(){
80matrixStack.clearStacks();
81framebufferIdStack.clear();
82}
83
84//----------------------------------------------------------
85void ofGLRenderer::draw(const ofMesh & vertexData, ofPolyRenderMode renderType, bool useColors, bool useTextures, bool useNormals) const{
86if (currentStyle.smoothing) const_cast<ofGLRenderer*>(this)->startSmoothing();
87#ifndef TARGET_OPENGLES
88glPolygonMode(GL_FRONT_AND_BACK, ofGetGLPolyMode(renderType));
89if(vertexData.getNumVertices()){
90glEnableClientState(GL_VERTEX_ARRAY);
91glVertexPointer(3, GL_FLOAT, sizeof(glm::vec3), &vertexData.getVerticesPointer()->x);
92}
93if(vertexData.getNumNormals() && useNormals){
94glEnableClientState(GL_NORMAL_ARRAY);
95glNormalPointer(GL_FLOAT, sizeof(glm::vec3), &vertexData.getNormalsPointer()->x);
96}
97if(vertexData.getNumColors() && useColors){
98glEnableClientState(GL_COLOR_ARRAY);
99glColorPointer(4,GL_FLOAT, sizeof(ofFloatColor), &vertexData.getColorsPointer()->r);
100}
101
102if(vertexData.getNumTexCoords() && useTextures){
103if(textureLocationsEnabled.size() == 0){
104glEnableClientState(GL_TEXTURE_COORD_ARRAY);
105glTexCoordPointer(2, GL_FLOAT, sizeof(glm::vec2), &vertexData.getTexCoordsPointer()->x);
106}else{
107std::set<int>::iterator textureLocation = textureLocationsEnabled.begin();
108for(;textureLocation!=textureLocationsEnabled.end();textureLocation++){
109glActiveTexture(GL_TEXTURE0+*textureLocation);
110glClientActiveTexture(GL_TEXTURE0+*textureLocation);
111glEnableClientState(GL_TEXTURE_COORD_ARRAY);
112glTexCoordPointer(2, GL_FLOAT, sizeof(glm::vec2), &vertexData.getTexCoordsPointer()->x);
113}
114glActiveTexture(GL_TEXTURE0);
115glClientActiveTexture(GL_TEXTURE0);
116}
117}
118
119if(vertexData.getNumIndices()){
120// This is never executed right now but this branch of the ifdef should be used for GLES 3 so let's keep it for future uses
121#ifdef TARGET_OPENGLES
122glDrawElements(ofGetGLPrimitiveMode(vertexData.getMode()), vertexData.getNumIndices(),GL_UNSIGNED_SHORT,vertexData.getIndexPointer());
123#else
124glDrawElements(ofGetGLPrimitiveMode(vertexData.getMode()), vertexData.getNumIndices(),GL_UNSIGNED_INT,vertexData.getIndexPointer());
125#endif
126}else{
127glDrawArrays(ofGetGLPrimitiveMode(vertexData.getMode()), 0, vertexData.getNumVertices());
128}
129
130if(vertexData.getNumColors() && useColors){
131glDisableClientState(GL_COLOR_ARRAY);
132}
133if(vertexData.getNumNormals() && useNormals){
134glDisableClientState(GL_NORMAL_ARRAY);
135}
136if(vertexData.getNumTexCoords() && useTextures){
137glDisableClientState(GL_TEXTURE_COORD_ARRAY);
138}
139glPolygonMode(GL_FRONT_AND_BACK, currentStyle.bFill ? GL_FILL : GL_LINE);
140#else
141if(vertexData.getNumVertices()){
142glEnableClientState(GL_VERTEX_ARRAY);
143glVertexPointer(3, GL_FLOAT, sizeof(typename ofMesh::VertexType), vertexData.getVerticesPointer());
144}
145if(vertexData.getNumNormals() && useNormals){
146glEnableClientState(GL_NORMAL_ARRAY);
147glNormalPointer(GL_FLOAT, 0, vertexData.getNormalsPointer());
148}
149if(vertexData.getNumColors() && useColors){
150glEnableClientState(GL_COLOR_ARRAY);
151glColorPointer(4,GL_FLOAT, sizeof(ofFloatColor), vertexData.getColorsPointer());
152}
153
154if(vertexData.getNumTexCoords() && useTextures){
155if(textureLocationsEnabled.size() == 0){
156glEnableClientState(GL_TEXTURE_COORD_ARRAY);
157glTexCoordPointer(2, GL_FLOAT, sizeof(typename ofMesh::TexCoordType), &vertexData.getTexCoordsPointer()->x);
158}else{
159std::set<int>::iterator textureLocation = textureLocationsEnabled.begin();
160for(;textureLocation!=textureLocationsEnabled.end();textureLocation++){
161glActiveTexture(GL_TEXTURE0+*textureLocation);
162glClientActiveTexture(GL_TEXTURE0+*textureLocation);
163glEnableClientState(GL_TEXTURE_COORD_ARRAY);
164glTexCoordPointer(2, GL_FLOAT, sizeof(typename ofMesh::TexCoordType), &vertexData.getTexCoordsPointer()->x);
165}
166glActiveTexture(GL_TEXTURE0);
167glClientActiveTexture(GL_TEXTURE0);
168}
169}
170
171GLenum drawMode;
172switch(renderType){
173case OF_MESH_POINTS:
174drawMode = GL_POINTS;
175break;
176case OF_MESH_WIREFRAME:
177drawMode = GL_LINES;
178break;
179case OF_MESH_FILL:
180drawMode = ofGetGLPrimitiveMode(vertexData.getMode());
181break;
182default:
183drawMode = ofGetGLPrimitiveMode(vertexData.getMode());
184break;
185}
186
187if(vertexData.getNumIndices()){
188glDrawElements(drawMode, vertexData.getNumIndices(),GL_UNSIGNED_SHORT,vertexData.getIndexPointer());
189}else{
190glDrawArrays(drawMode, 0, vertexData.getNumVertices());
191}
192if(vertexData.getNumColors() && useColors){
193glDisableClientState(GL_COLOR_ARRAY);
194}
195if(vertexData.getNumNormals() && useNormals){
196glDisableClientState(GL_NORMAL_ARRAY);
197}
198if(vertexData.getNumTexCoords() && useTextures){
199glDisableClientState(GL_TEXTURE_COORD_ARRAY);
200}
201#endif
202if (currentStyle.smoothing) const_cast<ofGLRenderer*>(this)->endSmoothing();
203}
204
205//----------------------------------------------------------
206void ofGLRenderer::draw(const ofVboMesh & mesh, ofPolyRenderMode renderType) const{
207drawInstanced(mesh,renderType,1);
208}
209
210//----------------------------------------------------------
211void ofGLRenderer::drawInstanced(const ofVboMesh & mesh, ofPolyRenderMode renderType, int primCount) const{
212if(mesh.getNumVertices()==0) return;
213GLuint mode = ofGetGLPrimitiveMode(mesh.getMode());
214#ifndef TARGET_OPENGLES
215glPolygonMode(GL_FRONT_AND_BACK, ofGetGLPolyMode(renderType));
216if(mesh.getNumIndices() && renderType!=OF_MESH_POINTS){
217if (primCount <= 1) {
218drawElements(mesh.getVbo(),mode,mesh.getNumIndices());
219} else {
220drawElementsInstanced(mesh.getVbo(),mode,mesh.getNumIndices(),primCount);
221}
222}else{
223if (primCount <= 1) {
224draw(mesh.getVbo(),mode,0,mesh.getNumVertices());
225} else {
226drawInstanced(mesh.getVbo(),mode,0,mesh.getNumVertices(),primCount);
227}
228}
229glPolygonMode(GL_FRONT_AND_BACK, currentStyle.bFill ? GL_FILL : GL_LINE);
230#else
231if(renderType == OF_MESH_POINTS){
232draw(mesh.getVbo(),GL_POINTS,0,mesh.getNumVertices());
233}else if(renderType == OF_MESH_WIREFRAME){
234if(mesh.getNumIndices()){
235drawElements(mesh.getVbo(),GL_LINES,mesh.getNumIndices());
236}else{
237draw(mesh.getVbo(),GL_LINES,0,mesh.getNumVertices());
238}
239}else{
240if(mesh.getNumIndices()){
241drawElements(mesh.getVbo(),mode,mesh.getNumIndices());
242}else{
243draw(mesh.getVbo(),mode,0,mesh.getNumVertices());
244}
245}
246#endif
247}
248
249//----------------------------------------------------------
250void ofGLRenderer::draw( const of3dPrimitive& model, ofPolyRenderMode renderType) const{
251const_cast<ofGLRenderer*>(this)->pushMatrix();
252const_cast<ofGLRenderer*>(this)->multMatrix(model.getGlobalTransformMatrix());
253if(model.isUsingVbo()){
254draw(static_cast<const ofVboMesh&>(model.getMesh()),renderType);
255}else{
256draw(model.getMesh(),renderType);
257}
258const_cast<ofGLRenderer*>(this)->popMatrix();
259}
260
261//----------------------------------------------------------
262void ofGLRenderer::draw(const ofNode& node) const{
263const_cast<ofGLRenderer*>(this)->pushMatrix();
264const_cast<ofGLRenderer*>(this)->multMatrix(node.getGlobalTransformMatrix());
265node.customDraw(this);
266const_cast<ofGLRenderer*>(this)->popMatrix();
267}
268
269//----------------------------------------------------------
270void ofGLRenderer::draw(const ofPolyline & poly) const{
271if(!poly.getVertices().empty()) {
272// use smoothness, if requested:
273if (currentStyle.smoothing) const_cast<ofGLRenderer*>(this)->startSmoothing();
274
275glEnableClientState(GL_VERTEX_ARRAY);
276glVertexPointer(3, GL_FLOAT, sizeof(glm::vec3), &poly.getVertices()[0].x);
277glDrawArrays(poly.isClosed()?GL_LINE_LOOP:GL_LINE_STRIP, 0, poly.size());
278
279// use smoothness, if requested:
280if (currentStyle.smoothing) const_cast<ofGLRenderer*>(this)->endSmoothing();
281}
282}
283
284//----------------------------------------------------------
285void ofGLRenderer::draw(const ofPath & shape) const{
286ofColor prevColor;
287if(shape.getUseShapeColor()){
288prevColor = currentStyle.color;
289}
290ofGLRenderer * mut_this = const_cast<ofGLRenderer*>(this);
291if(shape.isFilled()){
292const ofMesh & mesh = shape.getTessellation();
293if(shape.getUseShapeColor()){
294mut_this->setColor( shape.getFillColor(),shape.getFillColor().a);
295}
296draw(mesh,OF_MESH_FILL);
297}
298if(shape.hasOutline()){
299float lineWidth = currentStyle.lineWidth;
300if(shape.getUseShapeColor()){
301mut_this->setColor( shape.getStrokeColor(), shape.getStrokeColor().a);
302}
303mut_this->setLineWidth( shape.getStrokeWidth() );
304const vector<ofPolyline> & outlines = shape.getOutline();
305for(int i=0; i<(int)outlines.size(); i++)
306draw(outlines[i]);
307mut_this->setLineWidth(lineWidth);
308}
309if(shape.getUseShapeColor()){
310mut_this->setColor(prevColor);
311}
312}
313
314//----------------------------------------------------------
315void ofGLRenderer::draw(const ofImage & image, float x, float y, float z, float w, float h, float sx, float sy, float sw, float sh) const{
316if(image.isUsingTexture()){
317const ofTexture& tex = image.getTexture();
318if(tex.isAllocated()) {
319const_cast<ofGLRenderer*>(this)->bind(tex,0);
320draw(tex.getMeshForSubsection(x,y,z,w,h,sx,sy,sw,sh,isVFlipped(),currentStyle.rectMode),OF_MESH_FILL,false,true,false);
321const_cast<ofGLRenderer*>(this)->unbind(tex,0);
322} else {
323ofLogWarning("ofGLRenderer") << "drawing an unallocated texture";
324}
325}
326}
327
328//----------------------------------------------------------
329void ofGLRenderer::draw(const ofFloatImage & image, float x, float y, float z, float w, float h, float sx, float sy, float sw, float sh) const{
330if(image.isUsingTexture()){
331const ofTexture& tex = image.getTexture();
332if(tex.isAllocated()) {
333const_cast<ofGLRenderer*>(this)->bind(tex,0);
334draw(tex.getMeshForSubsection(x,y,z,w,h,sx,sy,sw,sh,isVFlipped(),currentStyle.rectMode),OF_MESH_FILL,false,true,false);
335const_cast<ofGLRenderer*>(this)->unbind(tex,0);
336} else {
337ofLogWarning("ofGLRenderer") << "draw(): texture is not allocated";
338}
339}
340}
341
342//----------------------------------------------------------
343void ofGLRenderer::draw(const ofShortImage & image, float x, float y, float z, float w, float h, float sx, float sy, float sw, float sh) const{
344if(image.isUsingTexture()){
345const ofTexture& tex = image.getTexture();
346if(tex.isAllocated()) {
347const_cast<ofGLRenderer*>(this)->bind(tex,0);
348draw(tex.getMeshForSubsection(x,y,z,w,h,sx,sy,sw,sh,isVFlipped(),currentStyle.rectMode),OF_MESH_FILL,false,true,false);
349const_cast<ofGLRenderer*>(this)->unbind(tex,0);
350} else {
351ofLogWarning("ofGLRenderer") << "draw(): texture is not allocated";
352}
353}
354}
355
356//----------------------------------------------------------
357void ofGLRenderer::draw(const ofTexture & tex, float x, float y, float z, float w, float h, float sx, float sy, float sw, float sh) const{
358if(tex.isAllocated()) {
359const_cast<ofGLRenderer*>(this)->bind(tex,0);
360draw(tex.getMeshForSubsection(x,y,z,w,h,sx,sy,sw,sh,isVFlipped(),currentStyle.rectMode),OF_MESH_FILL,false,true,false);
361const_cast<ofGLRenderer*>(this)->unbind(tex,0);
362} else {
363ofLogWarning("ofGLRenderer") << "draw(): texture is not allocated";
364}
365}
366
367//----------------------------------------------------------
368void ofGLRenderer::draw(const ofBaseVideoDraws & video, float x, float y, float w, float h) const{
369if(video.isInitialized() && video.isUsingTexture()){
370const_cast<ofGLRenderer*>(this)->bind(video);
371draw(video.getTexture().getMeshForSubsection(x,y,0,w,h,0,0,video.getWidth(),video.getHeight(),isVFlipped(),currentStyle.rectMode),OF_MESH_FILL,false,true,false);
372const_cast<ofGLRenderer*>(this)->unbind(video);
373}
374}
375
376//----------------------------------------------------------
377void ofGLRenderer::draw(const ofVbo & vbo, GLuint drawMode, int first, int total) const{
378if(vbo.getUsingVerts()) {
379vbo.bind();
380glDrawArrays(drawMode, first, total);
381vbo.unbind();
382}
383}
384
385//----------------------------------------------------------
386void ofGLRenderer::drawElements(const ofVbo & vbo, GLuint drawMode, int amt, int offsetelements) const{
387if(vbo.getUsingVerts()) {
388vbo.bind();
389#ifdef TARGET_OPENGLES
390glDrawElements(drawMode, amt, GL_UNSIGNED_SHORT, (void*)(sizeof(ofIndexType) * offsetelements));
391#else
392glDrawElements(drawMode, amt, GL_UNSIGNED_INT, (void*)(sizeof(ofIndexType) * offsetelements));
393#endif
394vbo.unbind();
395}
396}
397
398//----------------------------------------------------------
399void ofGLRenderer::drawInstanced(const ofVbo & vbo, GLuint drawMode, int first, int total, int primCount) const{
400if(vbo.getUsingVerts()) {
401vbo.bind();
402#ifdef TARGET_OPENGLES
403// todo: activate instancing once OPENGL ES supports instancing, starting with version 3.0
404// unfortunately there is currently no easy way within oF to query the current OpenGL version.
405// https://www.khronos.org/opengles/sdk/docs/man3/xhtml/glDrawElementsInstanced.xml
406ofLogWarning("ofVbo") << "drawInstanced(): hardware instancing is not supported on OpenGL ES < 3.0";
407// glDrawArraysInstanced(drawMode, first, total, primCount);
408#else
409glDrawArraysInstanced(drawMode, first, total, primCount);
410#endif
411vbo.unbind();
412}
413}
414
415//----------------------------------------------------------
416void ofGLRenderer::drawElementsInstanced(const ofVbo & vbo, GLuint drawMode, int amt, int primCount) const{
417if(vbo.getUsingVerts()) {
418vbo.bind();
419#ifdef TARGET_OPENGLES
420// todo: activate instancing once OPENGL ES supports instancing, starting with version 3.0
421// unfortunately there is currently no easy way within oF to query the current OpenGL version.
422// https://www.khronos.org/opengles/sdk/docs/man3/xhtml/glDrawElementsInstanced.xml
423ofLogWarning("ofVbo") << "drawElementsInstanced(): hardware instancing is not supported on OpenGL ES < 3.0";
424// glDrawElementsInstanced(drawMode, amt, GL_UNSIGNED_SHORT, nullptr, primCount);
425#else
426glDrawElementsInstanced(drawMode, amt, GL_UNSIGNED_INT, nullptr, primCount);
427#endif
428vbo.unbind();
429}
430}
431
432//----------------------------------------------------------
433ofPath & ofGLRenderer::getPath(){
434return path;
435}
436
437//----------------------------------------------------------
438void ofGLRenderer::bind(const ofBaseVideoDraws & video){
439if(video.isInitialized() && video.isUsingTexture()){
440bind(video.getTexture(),0);
441}
442}
443
444//----------------------------------------------------------
445void ofGLRenderer::unbind(const ofBaseVideoDraws & video){
446if(video.isInitialized() && video.isUsingTexture()){
447video.getTexture().unbind();
448}
449}
450
451//----------------------------------------------------------
452void ofGLRenderer::bind(const ofShader & shader){
453glUseProgram(shader.getProgram());
454}
455
456//----------------------------------------------------------
457void ofGLRenderer::unbind(const ofShader & shader){
458glUseProgram(0);
459}
460
461//----------------------------------------------------------
462void ofGLRenderer::begin(const ofFbo & fbo, ofFboMode mode){
463pushView();
464pushStyle();
465if(mode & OF_FBOMODE_MATRIXFLIP){
466matrixStack.setRenderSurface(fbo);
467}else{
468matrixStack.setRenderSurfaceNoMatrixFlip(fbo);
469}
470viewport();
471if(mode & OF_FBOMODE_PERSPECTIVE){
472setupScreenPerspective();
473}else{
474glm::mat4 m = glm::mat4(1.0);
475glGetFloatv(GL_PROJECTION_MATRIX, glm::value_ptr(m));
476m = matrixStack.getOrientationMatrixInverse() * m;
477ofMatrixMode currentMode = matrixStack.getCurrentMatrixMode();
478matrixStack.matrixMode(OF_MATRIX_PROJECTION);
479matrixStack.loadMatrix(m);
480glMatrixMode(GL_PROJECTION);
481glLoadMatrixf(glm::value_ptr(matrixStack.getProjectionMatrix()));
482matrixMode(currentMode);
483}
484bind(fbo);
485}
486
487//----------------------------------------------------------
488void ofGLRenderer::end(const ofFbo & fbo){
489unbind(fbo);
490matrixStack.setRenderSurface(*window);
491popStyle();
492popView();
493}
494
495//----------------------------------------------------------
496void ofGLRenderer::bind(const ofFbo & fbo){
497if (currentFramebufferId == fbo.getId()){
498ofLogWarning() << "Framebuffer with id: " << fbo.getId() << " cannot be bound onto itself. \n" <<
499"Most probably you forgot to end() the current framebuffer before calling begin() again or you forgot to allocate() before calling begin().";
500return;
501}
502// this method could just as well have been placed in ofBaseGLRenderer
503// and shared over both programmable and fixed function renderer.
504// I'm keeping it here, so that if we want to do more fancyful
505// named framebuffers with GL 4.5+, we can have
506// different implementations.
507framebufferIdStack.push_back(currentFramebufferId);
508currentFramebufferId = fbo.getId();
509glBindFramebuffer(GL_FRAMEBUFFER, currentFramebufferId);
510}
511
512#ifndef TARGET_OPENGLES
513//----------------------------------------------------------
514void ofGLRenderer::bindForBlitting(const ofFbo & fboSrc, ofFbo & fboDst, int attachmentPoint){
515if (currentFramebufferId == fboSrc.getId()){
516ofLogWarning() << "Framebuffer with id: " << fboSrc.getId() << " cannot be bound onto itself. \n" <<
517"Most probably you forgot to end() the current framebuffer before calling getTexture().";
518return;
519}
520// this method could just as well have been placed in ofBaseGLRenderer
521// and shared over both programmable and fixed function renderer.
522// I'm keeping it here, so that if we want to do more fancyful
523// named framebuffers with GL 4.5+, we can have
524// different implementations.
525framebufferIdStack.push_back(currentFramebufferId);
526currentFramebufferId = fboSrc.getId();
527glBindFramebuffer(GL_READ_FRAMEBUFFER, currentFramebufferId);
528glReadBuffer(GL_COLOR_ATTACHMENT0 + attachmentPoint);
529glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboDst.getIdDrawBuffer());
530glDrawBuffer(GL_COLOR_ATTACHMENT0 + attachmentPoint);
531}
532#endif
533
534//----------------------------------------------------------
535void ofGLRenderer::unbind(const ofFbo & fbo){
536if(framebufferIdStack.empty()){
537ofLogError() << "unbalanced fbo bind/unbind binding default framebuffer";
538currentFramebufferId = defaultFramebufferId;
539}else{
540currentFramebufferId = framebufferIdStack.back();
541framebufferIdStack.pop_back();
542}
543glBindFramebuffer(GL_FRAMEBUFFER, currentFramebufferId);
544fbo.flagDirty();
545}
546
547//----------------------------------------------------------
548void ofGLRenderer::bind(const ofBaseMaterial & material){
549ofFloatColor diffuse = material.getDiffuseColor();
550ofFloatColor specular = material.getSpecularColor();
551ofFloatColor ambient = material.getAmbientColor();
552ofFloatColor emissive = material.getEmissiveColor();
553float shininess = material.getShininess();
554glDisable(GL_COLOR_MATERIAL);
555glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.r);
556glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r);
557glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.r);
558glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &emissive.r);
559glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &shininess);
560materialBound = true;
561}
562
563//----------------------------------------------------------
564void ofGLRenderer::unbind(const ofBaseMaterial &){
565// Set default material colors and properties
566ofMaterial::Data defaultData;
567glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, &defaultData.diffuse.r);
568glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &defaultData.specular.r);
569glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, &defaultData.ambient.r);
570glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &defaultData.emissive.r);
571glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &defaultData.shininess);
572// Re-enable global color as material ambient and diffuse
573materialBound = false;
574if(lightingEnabled){
575setColor(currentStyle.color);
576}
577}
578
579// does nothing, only programmable renderer supported
580//----------------------------------------------------------
581void ofGLRenderer::bind(const ofShadow & shadow) {
582ofLogWarning("ofGLRenderer::bind(const ofShadow & shadow) : shadows are only supported via programmable renderer");
583};
584//----------------------------------------------------------
585void ofGLRenderer::bind(const ofShadow & shadow, GLenum aCubeFace) {
586ofLogWarning("ofGLRenderer::bind(const ofShadow & shadow) : shadows are only supported via programmable renderer");
587};
588
589// does nothing, only programmable renderer supported
590//----------------------------------------------------------
591void ofGLRenderer::unbind(const ofShadow & shadow) {};
592//----------------------------------------------------------
593void ofGLRenderer::unbind(const ofShadow & shadow, GLenum aCubeFace) {};
594
595//----------------------------------------------------------
596void ofGLRenderer::bind(const ofTexture & texture, int location){
597//we could check if it has been allocated - but we don't do that in draw()
598if(texture.getAlphaMask()){
599setAlphaMaskTex(*texture.getAlphaMask());
600}
601enableTextureTarget(texture,location);
602
603
604if(ofGetUsingNormalizedTexCoords()) {
605matrixMode(OF_MATRIX_TEXTURE);
606pushMatrix();
607glm::mat4 m = glm::mat4(1.0);
608
609#ifndef TARGET_OPENGLES
610if(texture.texData.textureTarget == GL_TEXTURE_RECTANGLE_ARB)
611m = glm::scale(m, glm::vec3(texture.texData.width, texture.texData.height, 1.0f));
612else
613#endif
614m = glm::scale(m, glm::vec3(texture.texData.width / texture.texData.tex_w, texture.texData.height / texture.texData.tex_h, 1.0f));
615
616loadMatrix(m);
617matrixMode(OF_MATRIX_MODELVIEW);
618}
619if(texture.isUsingTextureMatrix()){
620matrixMode(OF_MATRIX_TEXTURE);
621if(!ofGetUsingNormalizedTexCoords()) pushMatrix();
622multMatrix(texture.getTextureMatrix());
623matrixMode(OF_MATRIX_MODELVIEW);
624}
625}
626
627//----------------------------------------------------------
628void ofGLRenderer::unbind(const ofTexture & texture, int location){
629disableTextureTarget(texture.texData.textureTarget,location);
630if(texture.getAlphaMask()){
631disableAlphaMask();
632}
633
634if(texture.isUsingTextureMatrix() || ofGetUsingNormalizedTexCoords()) {
635matrixMode(OF_MATRIX_TEXTURE);
636popMatrix();
637matrixMode(OF_MATRIX_MODELVIEW);
638}
639}
640
641//----------------------------------------------------------
642void ofGLRenderer::bind(const ofCamera & camera, const ofRectangle & _viewport){
643pushView();
644viewport(_viewport);
645setOrientation(matrixStack.getOrientation(),camera.isVFlipped());
646matrixMode(OF_MATRIX_PROJECTION);
647loadMatrix(camera.getProjectionMatrix(_viewport));
648matrixMode(OF_MATRIX_MODELVIEW);
649loadViewMatrix(camera.getModelViewMatrix());
650}
651
652//----------------------------------------------------------
653void ofGLRenderer::unbind(const ofCamera & camera){
654popView();
655}
656
657//----------------------------------------------------------
658void ofGLRenderer::pushView() {
659getCurrentViewport();
660
661glm::mat4 m = glm::mat4(1.0);
662ofMatrixMode matrixMode = matrixStack.getCurrentMatrixMode();
663glGetFloatv(GL_PROJECTION_MATRIX,glm::value_ptr(m));
664matrixStack.matrixMode(OF_MATRIX_PROJECTION);
665matrixStack.loadMatrix(m);
666glGetFloatv(GL_MODELVIEW_MATRIX,glm::value_ptr(m));
667matrixStack.matrixMode(OF_MATRIX_MODELVIEW);
668matrixStack.loadMatrix(m);
669
670matrixStack.matrixMode(matrixMode);
671
672matrixStack.pushView();
673}
674
675
676//----------------------------------------------------------
677void ofGLRenderer::popView() {
678matrixStack.popView();
679
680ofMatrixMode currentMode = matrixStack.getCurrentMatrixMode();
681
682matrixMode(OF_MATRIX_PROJECTION);
683loadMatrix(matrixStack.getProjectionMatrix());
684
685matrixMode(OF_MATRIX_MODELVIEW);
686loadMatrix(matrixStack.getModelViewMatrix());
687
688matrixMode(currentMode);
689
690viewport(matrixStack.getCurrentViewport());
691}
692
693
694//----------------------------------------------------------
695void ofGLRenderer::viewport(ofRectangle viewport_){
696viewport(viewport_.x, viewport_.y, viewport_.width, viewport_.height, isVFlipped());
697}
698
699//----------------------------------------------------------
700void ofGLRenderer::viewport(float x, float y, float width, float height, bool vflip) {
701matrixStack.viewport(x,y,width,height,vflip);
702ofRectangle nativeViewport = matrixStack.getNativeViewport();
703glViewport(nativeViewport.x,nativeViewport.y,nativeViewport.width,nativeViewport.height);
704}
705
706//----------------------------------------------------------
707ofRectangle ofGLRenderer::getCurrentViewport() const{
708getNativeViewport();
709return matrixStack.getCurrentViewport();
710}
711
712//----------------------------------------------------------
713ofRectangle ofGLRenderer::getNativeViewport() const{
714GLint viewport[4]; // Where The Viewport Values Will Be Stored
715glGetIntegerv(GL_VIEWPORT, viewport);
716
717ofGLRenderer * mutRenderer = const_cast<ofGLRenderer*>(this);
718ofRectangle nativeViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
719mutRenderer->matrixStack.nativeViewport(nativeViewport);
720return nativeViewport;
721}
722
723//----------------------------------------------------------
724int ofGLRenderer::getViewportWidth() const{
725return getCurrentViewport().width;
726}
727
728//----------------------------------------------------------
729int ofGLRenderer::getViewportHeight() const{
730return getCurrentViewport().height;
731}
732
733//----------------------------------------------------------
734void ofGLRenderer::setCoordHandedness(ofHandednessType handedness) {
735
736}
737
738//----------------------------------------------------------
739ofHandednessType ofGLRenderer::getCoordHandedness() const{
740return matrixStack.getHandedness();
741}
742
743//----------------------------------------------------------
744void ofGLRenderer::setOrientation(ofOrientation orientation, bool vFlip){
745matrixStack.setOrientation(orientation,vFlip);
746}
747
748//----------------------------------------------------------
749bool ofGLRenderer::isVFlipped() const{
750return matrixStack.isVFlipped();
751}
752
753//----------------------------------------------------------
754bool ofGLRenderer::texturesNeedVFlip() const{
755return matrixStack.customMatrixNeedsFlip();
756}
757
758//----------------------------------------------------------
759void ofGLRenderer::setupScreenPerspective(float width, float height, float fov, float nearDist, float farDist) {
760float viewW, viewH;
761if(width<0 || height<0){
762ofRectangle currentViewport = getCurrentViewport();
763
764viewW = currentViewport.width;
765viewH = currentViewport.height;
766}else{
767viewW = width;
768viewH = height;
769}
770
771float eyeX = viewW / 2;
772float eyeY = viewH / 2;
773float halfFov = glm::pi<float>() * fov / 360.0f;
774float theTan = tanf(halfFov);
775float dist = eyeY / theTan;
776float aspect = (float) viewW / viewH;
777
778if(nearDist == 0) nearDist = dist / 10.0f;
779if(farDist == 0) farDist = dist * 10.0f;
780
781
782matrixMode(OF_MATRIX_PROJECTION);
783glm::mat4 persp = glm::perspective(ofDegToRad(fov), aspect, nearDist, farDist);
784loadMatrix( persp );
785
786matrixMode(OF_MATRIX_MODELVIEW);
787glm::mat4 lookAtMat = glm::lookAt( glm::vec3(eyeX, eyeY, dist), glm::vec3(eyeX, eyeY, 0), glm::vec3(0, 1, 0) );
788loadViewMatrix(lookAtMat);
789}
790
791//----------------------------------------------------------
792void ofGLRenderer::setupScreenOrtho(float width, float height, float nearDist, float farDist) {
793float viewW, viewH;
794if(width<0 || height<0){
795ofRectangle currentViewport = getCurrentViewport();
796
797viewW = currentViewport.width;
798viewH = currentViewport.height;
799}else{
800viewW = width;
801viewH = height;
802}
803
804glm::mat4 orthoMat = glm::ortho(0.f, viewW, 0.f, viewH, nearDist, farDist);
805
806matrixMode(OF_MATRIX_PROJECTION);
807loadMatrix(orthoMat); // make ortho our new projection matrix.
808
809matrixMode(OF_MATRIX_MODELVIEW);
810loadViewMatrix(glm::mat4(1.0));
811
812}
813
814//----------------------------------------------------------
815//Resets openGL parameters back to OF defaults
816void ofGLRenderer::setupGraphicDefaults(){
817glEnableClientState(GL_VERTEX_ARRAY);
818glDisableClientState(GL_NORMAL_ARRAY);
819glDisableClientState(GL_COLOR_ARRAY);
820glDisableClientState(GL_TEXTURE_COORD_ARRAY);
821setStyle(ofStyle());
822path.setMode(ofPath::POLYLINES);
823path.setUseShapeColor(false);
824}
825
826//----------------------------------------------------------
827void ofGLRenderer::setupScreen(){
828setupScreenPerspective(); // assume defaults
829}
830
831//----------------------------------------------------------
832void ofGLRenderer::setCircleResolution(int res){
833if((int)circlePolyline.size()!=res+1){
834circlePolyline.clear();
835circlePolyline.arc(0,0,0,1,1,0,360,res);
836circlePoints.resize(circlePolyline.size());
837path.setCircleResolution(res);
838}
839currentStyle.circleResolution = res;
840}
841
842void ofGLRenderer::setPolyMode(ofPolyWindingMode mode){
843currentStyle.polyMode = mode;
844path.setPolyWindingMode(mode);
845}
846
847//our openGL wrappers
848//----------------------------------------------------------
849void ofGLRenderer::pushMatrix(){
850glPushMatrix();
851}
852
853//----------------------------------------------------------
854void ofGLRenderer::popMatrix(){
855glPopMatrix();
856}
857
858//----------------------------------------------------------
859void ofGLRenderer::translate(const glm::vec3& p){
860glTranslatef(p.x, p.y, p.z);
861}
862
863//----------------------------------------------------------
864void ofGLRenderer::translate(float x, float y, float z){
865glTranslatef(x, y, z);
866}
867
868//----------------------------------------------------------
869void ofGLRenderer::scale(float xAmnt, float yAmnt, float zAmnt){
870glScalef(xAmnt, yAmnt, zAmnt);
871}
872
873//----------------------------------------------------------
874void ofGLRenderer::rotateDeg(float degrees, float vecX, float vecY, float vecZ){
875glRotatef(degrees, vecX, vecY, vecZ);
876}
877
878//----------------------------------------------------------
879void ofGLRenderer::rotateXDeg(float degrees){
880glRotatef(degrees, 1, 0, 0);
881}
882
883//----------------------------------------------------------
884void ofGLRenderer::rotateYDeg(float degrees){
885glRotatef(degrees, 0, 1, 0);
886}
887
888//----------------------------------------------------------
889void ofGLRenderer::rotateZDeg(float degrees){
890glRotatef(degrees, 0, 0, 1);
891}
892
893//same as ofRotateZ
894//----------------------------------------------------------
895void ofGLRenderer::rotateDeg(float degrees){
896glRotatef(degrees, 0, 0, 1);
897}
898
899//----------------------------------------------------------
900void ofGLRenderer::rotateRad(float radians, float vecX, float vecY, float vecZ){
901glRotatef(ofRadToDeg(radians), vecX, vecY, vecZ);
902}
903
904//----------------------------------------------------------
905void ofGLRenderer::rotateXRad(float radians){
906glRotatef(ofRadToDeg(radians), 1, 0, 0);
907}
908
909//----------------------------------------------------------
910void ofGLRenderer::rotateYRad(float radians){
911glRotatef(ofRadToDeg(radians), 0, 1, 0);
912}
913
914//----------------------------------------------------------
915void ofGLRenderer::rotateZRad(float radians){
916glRotatef(ofRadToDeg(radians), 0, 0, 1);
917}
918
919//same as ofRotateZ
920//----------------------------------------------------------
921void ofGLRenderer::rotateRad(float radians){
922glRotatef(ofRadToDeg(radians), 0, 0, 1);
923}
924
925//----------------------------------------------------------
926void ofGLRenderer::matrixMode(ofMatrixMode mode){
927glMatrixMode(GL_MODELVIEW+mode);
928matrixStack.matrixMode(mode);
929}
930
931//----------------------------------------------------------
932void ofGLRenderer::loadIdentityMatrix (void){
933loadMatrix(glm::mat4(1.0));
934}
935
936//----------------------------------------------------------
937void ofGLRenderer::loadMatrix (const glm::mat4 & m){
938if(matrixStack.getCurrentMatrixMode()==OF_MATRIX_PROJECTION){
939matrixStack.loadMatrix(m);
940glLoadMatrixf(glm::value_ptr(matrixStack.getProjectionMatrix()));
941}else{
942glLoadMatrixf(glm::value_ptr(m));
943}
944}
945
946//----------------------------------------------------------
947void ofGLRenderer::loadMatrix (const float *m){
948loadMatrix( glm::make_mat4(m) );
949}
950
951//----------------------------------------------------------
952
953/** @brief Queries the current OpenGL matrix state
954* @detail Returns the specified matrix as held by the renderer's current matrix stack.
955*
956* You can query one of the following:
957*
958* [OF_MATRIX_MODELVIEW | OF_MATRIX_PROJECTION | OF_MATRIX_TEXTURE]
959*
960* Each query will return the state of the matrix
961* as it was uploaded to the shader currently bound.
962*
963* @param matrixMode_ Which matrix mode to query
964*/
965glm::mat4 ofGLRenderer::getCurrentMatrix(ofMatrixMode matrixMode_) const {
966glm::mat4 mat = glm::mat4(1.0);
967switch (matrixMode_) {
968case OF_MATRIX_MODELVIEW:
969glGetFloatv(GL_MODELVIEW_MATRIX, glm::value_ptr(mat));
970break;
971case OF_MATRIX_PROJECTION:
972glGetFloatv(GL_PROJECTION_MATRIX, glm::value_ptr(mat));
973break;
974case OF_MATRIX_TEXTURE:
975glGetFloatv(GL_TEXTURE_MATRIX, glm::value_ptr(mat));
976break;
977default:
978ofLogWarning() << "Invalid getCurrentMatrix query";
979break;
980}
981return mat;
982}
983
984//----------------------------------------------------------
985glm::mat4 ofGLRenderer::getCurrentOrientationMatrix() const {
986return matrixStack.getOrientationMatrix();
987}
988
989//----------------------------------------------------------
990void ofGLRenderer::multMatrix (const glm::mat4 & m){
991if(matrixStack.getCurrentMatrixMode()==OF_MATRIX_PROJECTION){
992glm::mat4 current = glm::mat4(1.0);
993glGetFloatv(GL_PROJECTION_MATRIX, glm::value_ptr(current));
994if(matrixStack.customMatrixNeedsFlip()){
995current = glm::scale(current, glm::vec3(1,-1,1));
996}
997matrixStack.loadMatrix(current);
998matrixStack.multMatrix(m);
999glLoadMatrixf(glm::value_ptr(matrixStack.getProjectionMatrix()));
1000}else{
1001glMultMatrixf(glm::value_ptr(m));
1002}
1003}
1004
1005//----------------------------------------------------------
1006void ofGLRenderer::multMatrix (const float *m){
1007multMatrix( glm::make_mat4(m) );
1008}
1009
1010//----------------------------------------------------------
1011void ofGLRenderer::loadViewMatrix(const glm::mat4 & m){
1012int matrixMode;
1013glGetIntegerv(GL_MATRIX_MODE,&matrixMode);
1014matrixStack.loadViewMatrix(m);
1015glMatrixMode(GL_MODELVIEW);
1016glLoadMatrixf(glm::value_ptr(m));
1017glMatrixMode(matrixMode);
1018
1019if(lightingEnabled){
1020for(size_t i=0;i<ofLightsData().size();i++){
1021shared_ptr<ofLight::Data> lightData = ofLightsData()[i].lock();
1022if(lightData && lightData->isEnabled){
1023glLightfv(GL_LIGHT0 + lightData->glIndex, GL_POSITION, &lightData->position.x);
1024if(lightData->lightType == OF_LIGHT_SPOT || lightData->lightType == OF_LIGHT_AREA) {
1025glLightfv(GL_LIGHT0 + lightData->glIndex, GL_SPOT_DIRECTION, &lightData->direction.x);
1026}
1027}
1028}
1029}
1030}
1031
1032//----------------------------------------------------------
1033void ofGLRenderer::multViewMatrix(const glm::mat4 & m){
1034ofLogError() << "mutlViewMatrix not implemented on fixed GL renderer";
1035}
1036
1037//----------------------------------------------------------
1038glm::mat4 ofGLRenderer::getCurrentViewMatrix() const{
1039return matrixStack.getViewMatrix();
1040}
1041
1042//----------------------------------------------------------
1043glm::mat4 ofGLRenderer::getCurrentNormalMatrix() const{
1044return glm::transpose(glm::inverse(getCurrentMatrix(OF_MATRIX_MODELVIEW)));
1045}
1046
1047//----------------------------------------------------------
1048void ofGLRenderer::setColor(const ofColor & color){
1049setColor(color.r,color.g,color.b,color.a);
1050}
1051
1052//----------------------------------------------------------
1053void ofGLRenderer::setColor(const ofColor & color, int _a){
1054setColor(color.r,color.g,color.b,_a);
1055}
1056
1057//----------------------------------------------------------
1058void ofGLRenderer::setColor(int r, int g, int b){
1059currentStyle.color.set(r,g,b);
1060glColor4f(r/255.f,g/255.f,b/255.f,1.f);
1061if(lightingEnabled && !materialBound){
1062#ifndef TARGET_OPENGLES
1063glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
1064#endif
1065glEnable(GL_COLOR_MATERIAL);
1066}
1067}
1068
1069
1070//----------------------------------------------------------
1071void ofGLRenderer::setColor(int r, int g, int b, int a){
1072currentStyle.color.set(r,g,b,a);
1073glColor4f(r/255.f,g/255.f,b/255.f,a/255.f);
1074if(lightingEnabled && !materialBound){
1075#ifndef TARGET_OPENGLES
1076glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
1077#endif
1078glEnable(GL_COLOR_MATERIAL);
1079}
1080}
1081
1082//----------------------------------------------------------
1083void ofGLRenderer::setColor(int gray){
1084setColor(gray, gray, gray);
1085}
1086
1087//----------------------------------------------------------
1088void ofGLRenderer::setHexColor(int hexColor){
1089int r = (hexColor >> 16) & 0xff;
1090int g = (hexColor >> 8) & 0xff;
1091int b = (hexColor >> 0) & 0xff;
1092setColor(r,g,b);
1093}
1094
1095//----------------------------------------------------------
1096void ofGLRenderer::clear(){
1097glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1098}
1099
1100//----------------------------------------------------------
1101void ofGLRenderer::clear(float r, float g, float b, float a) {
1102glClearColor(r / 255., g / 255., b / 255., a / 255.);
1103glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1104}
1105
1106//----------------------------------------------------------
1107void ofGLRenderer::clear(float brightness, float a) {
1108clear(brightness, brightness, brightness, a);
1109}
1110
1111//----------------------------------------------------------
1112void ofGLRenderer::clearAlpha() {
1113glColorMask(0, 0, 0, 1);
1114glClearColor(0, 0, 0, 1);
1115glClear(GL_COLOR_BUFFER_BIT);
1116glColorMask(1, 1, 1, 1);
1117}
1118
1119//----------------------------------------------------------
1120void ofGLRenderer::setBackgroundAuto(bool bAuto){
1121bBackgroundAuto = bAuto;
1122}
1123
1124//----------------------------------------------------------
1125bool ofGLRenderer::getBackgroundAuto(){
1126return bBackgroundAuto;
1127}
1128
1129//----------------------------------------------------------
1130ofColor ofGLRenderer::getBackgroundColor(){
1131return currentStyle.bgColor;
1132}
1133
1134//----------------------------------------------------------
1135void ofGLRenderer::setBackgroundColor(const ofColor & color){
1136currentStyle.bgColor = color;
1137glClearColor(currentStyle.bgColor[0]/255.,currentStyle.bgColor[1]/255.,currentStyle.bgColor[2]/255., currentStyle.bgColor[3]/255.);
1138}
1139
1140//----------------------------------------------------------
1141void ofGLRenderer::background(const ofColor & c){
1142setBackgroundColor(c);
1143glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1144}
1145
1146//----------------------------------------------------------
1147void ofGLRenderer::background(float brightness) {
1148background(ofColor(brightness));
1149}
1150
1151//----------------------------------------------------------
1152void ofGLRenderer::background(int hexColor, float _a){
1153background ( (hexColor >> 16) & 0xff, (hexColor >> 8) & 0xff, (hexColor >> 0) & 0xff, _a);
1154}
1155
1156//----------------------------------------------------------
1157void ofGLRenderer::background(int r, int g, int b, int a){
1158background(ofColor(r,g,b,a));
1159}
1160
1161//----------------------------------------------------------
1162void ofGLRenderer::setFillMode(ofFillFlag fill){
1163currentStyle.bFill = (fill==OF_FILLED);
1164if(currentStyle.bFill){
1165path.setFilled(true);
1166path.setStrokeWidth(0);
1167#ifndef TARGET_OPENGLES
1168// GLES does not support glPolygonMode
1169glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1170#endif
1171}else{
1172path.setFilled(false);
1173path.setStrokeWidth(currentStyle.lineWidth);
1174#ifndef TARGET_OPENGLES
1175// GLES does not support glPolygonMode
1176glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1177#endif
1178}
1179}
1180
1181//----------------------------------------------------------
1182ofFillFlag ofGLRenderer::getFillMode(){
1183if(currentStyle.bFill){
1184return OF_FILLED;
1185}else{
1186return OF_OUTLINE;
1187}
1188}
1189
1190//----------------------------------------------------------
1191void ofGLRenderer::setRectMode(ofRectMode mode){
1192currentStyle.rectMode = mode;
1193}
1194
1195//----------------------------------------------------------
1196ofRectMode ofGLRenderer::getRectMode(){
1197return currentStyle.rectMode;
1198}
1199
1200//----------------------------------------------------------
1201void ofGLRenderer::setLineWidth(float lineWidth){
1202currentStyle.lineWidth = lineWidth;
1203if(!currentStyle.bFill){
1204path.setStrokeWidth(lineWidth);
1205}
1206glLineWidth(lineWidth);
1207}
1208
1209//----------------------------------------------------------
1210void ofGLRenderer::setDepthTest(bool depthTest){
1211if(depthTest) {
1212glEnable(GL_DEPTH_TEST);
1213} else {
1214glDisable(GL_DEPTH_TEST);
1215}
1216}
1217
1218//----------------------------------------------------------
1219void ofGLRenderer::setLineSmoothing(bool smooth){
1220currentStyle.smoothing = smooth;
1221}
1222
1223
1224//----------------------------------------------------------
1225void ofGLRenderer::startSmoothing(){
1226#ifndef TARGET_OPENGLES
1227glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
1228#endif
1229
1230glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
1231glEnable(GL_LINE_SMOOTH);
1232
1233//why do we need this?
1234glEnable(GL_BLEND);
1235glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1236}
1237
1238
1239//----------------------------------------------------------
1240void ofGLRenderer::endSmoothing(){
1241#ifndef TARGET_OPENGLES
1242glPopAttrib();
1243#endif
1244}
1245
1246//----------------------------------------------------------
1247void ofGLRenderer::setBlendMode(ofBlendMode blendMode){
1248switch (blendMode){
1249case OF_BLENDMODE_DISABLED:
1250glDisable(GL_BLEND);
1251break;
1252
1253case OF_BLENDMODE_ALPHA:{
1254glEnable(GL_BLEND);
1255#ifndef TARGET_OPENGLES
1256glBlendEquation(GL_FUNC_ADD);
1257#endif
1258glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1259break;
1260}
1261
1262case OF_BLENDMODE_ADD:{
1263glEnable(GL_BLEND);
1264#ifndef TARGET_OPENGLES
1265glBlendEquation(GL_FUNC_ADD);
1266#endif
1267glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1268break;
1269}
1270
1271case OF_BLENDMODE_MULTIPLY:{
1272glEnable(GL_BLEND);
1273#ifndef TARGET_OPENGLES
1274glBlendEquation(GL_FUNC_ADD);
1275#endif
1276glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA /* GL_ZERO or GL_ONE_MINUS_SRC_ALPHA */);
1277break;
1278}
1279
1280case OF_BLENDMODE_SCREEN:{
1281glEnable(GL_BLEND);
1282#ifndef TARGET_OPENGLES
1283glBlendEquation(GL_FUNC_ADD);
1284#endif
1285glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE);
1286break;
1287}
1288
1289case OF_BLENDMODE_SUBTRACT:{
1290glEnable(GL_BLEND);
1291#ifndef TARGET_OPENGLES
1292glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
1293#else
1294ofLogWarning("ofGLRenderer") << "OF_BLENDMODE_SUBTRACT not currently supported on OpenGL ES";
1295#endif
1296glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1297break;
1298}
1299
1300default:
1301break;
1302}
1303currentStyle.blendingMode = blendMode;
1304}
1305
1306//----------------------------------------------------------
1307void ofGLRenderer::setBitmapTextMode(ofDrawBitmapMode mode){
1308currentStyle.drawBitmapMode = mode;
1309}
1310
1311//----------------------------------------------------------
1312ofStyle ofGLRenderer::getStyle() const{
1313return currentStyle;
1314}
1315
1316//----------------------------------------------------------
1317void ofGLRenderer::pushStyle(){
1318styleHistory.push_back(currentStyle);
1319//if we are over the max number of styles we have set, then delete the oldest styles.
1320if( styleHistory.size() > OF_MAX_STYLE_HISTORY ){
1321styleHistory.pop_front();
1322//should we warn here?
1323ofLogWarning("ofGraphics") << "ofPushStyle(): maximum number of style pushes << " << OF_MAX_STYLE_HISTORY << " reached, did you forget to pop somewhere?";
1324}
1325}
1326
1327//----------------------------------------------------------
1328void ofGLRenderer::popStyle(){
1329if( styleHistory.size() ){
1330setStyle(styleHistory.back());
1331styleHistory.pop_back();
1332}
1333}
1334
1335//----------------------------------------------------------
1336void ofGLRenderer::setStyle(const ofStyle & style){
1337//color
1338setColor((int)style.color.r, (int)style.color.g, (int)style.color.b, (int)style.color.a);
1339
1340//bg color
1341setBackgroundColor(style.bgColor);
1342
1343//circle resolution - don't worry it only recalculates the display list if the res has changed
1344setCircleResolution(style.circleResolution);
1345
1346setCurveResolution(style.curveResolution);
1347
1348//line width - finally!
1349setLineWidth(style.lineWidth);
1350
1351//ofSetDepthTest(style.depthTest); removed since it'll break old projects setting depth test through glEnable
1352
1353//rect mode: corner/center
1354setRectMode(style.rectMode);
1355
1356//poly mode: winding type
1357setPolyMode(style.polyMode);
1358
1359//fill
1360if(style.bFill ){
1361setFillMode(OF_FILLED);
1362}else{
1363setFillMode(OF_OUTLINE);
1364}
1365
1366//smoothing
1367/*if(style.smoothing ){
1368enableSmoothing();
1369}else{
1370disableSmoothing();
1371}*/
1372
1373//blending
1374setBlendMode(style.blendingMode);
1375
1376currentStyle = style;
1377}
1378
1379//----------------------------------------------------------
1380void ofGLRenderer::setCurveResolution(int resolution){
1381currentStyle.curveResolution = resolution;
1382path.setCurveResolution(resolution);
1383}
1384
1385//----------------------------------------------------------
1386void ofGLRenderer::enablePointSprites(){
1387
1388#ifdef TARGET_OPENGLES
1389glEnable(GL_POINT_SPRITE_OES);
1390glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE);
1391// does look like this needs to be enabled in ES because
1392// it is always eneabled...
1393//glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
1394
1395#else
1396glEnable(GL_POINT_SPRITE);
1397glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
1398glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
1399#endif
1400
1401}
1402
1403//----------------------------------------------------------
1404void ofGLRenderer::disablePointSprites(){
1405
1406#ifdef TARGET_OPENGLES
1407glDisable(GL_POINT_SPRITE_OES);
1408#else
1409glDisable(GL_POINT_SPRITE);
1410#endif
1411}
1412
1413//----------------------------------------------------------
1414void ofGLRenderer::enableAntiAliasing(){
1415glEnable(GL_MULTISAMPLE);
1416}
1417
1418//----------------------------------------------------------
1419void ofGLRenderer::disableAntiAliasing(){
1420glDisable(GL_MULTISAMPLE);
1421}
1422
1423//----------------------------------------------------------
1424void ofGLRenderer::drawLine(float x1, float y1, float z1, float x2, float y2, float z2) const{
1425linePoints[0] = {x1,y1,z1};
1426linePoints[1] = {x2,y2,z2};
1427
1428// use smoothness, if requested:
1429if (currentStyle.smoothing) const_cast<ofGLRenderer*>(this)->startSmoothing();
1430
1431glEnableClientState(GL_VERTEX_ARRAY);
1432glVertexPointer(3, GL_FLOAT, sizeof(glm::vec3), linePoints.data());
1433glDrawArrays(GL_LINES, 0, 2);
1434
1435// use smoothness, if requested:
1436if (currentStyle.smoothing) const_cast<ofGLRenderer*>(this)->endSmoothing();
1437
1438}
1439
1440//----------------------------------------------------------
1441void ofGLRenderer::drawRectangle(float x, float y, float z,float w, float h) const{
1442
1443if (currentStyle.rectMode == OF_RECTMODE_CORNER){
1444rectPoints[0] = {x,y,z};
1445rectPoints[1] = {x+w, y, z};
1446rectPoints[2] = {x+w, y+h, z};
1447rectPoints[3] = {x, y+h, z};
1448}else{
1449rectPoints[0] = {x-w/2.0f, y-h/2.0f, z};
1450rectPoints[1] = {x+w/2.0f, y-h/2.0f, z};
1451rectPoints[2] = {x+w/2.0f, y+h/2.0f, z};
1452rectPoints[3] = {x-w/2.0f, y+h/2.0f, z};
1453}
1454
1455// use smoothness, if requested:
1456if (currentStyle.smoothing && !currentStyle.bFill) const_cast<ofGLRenderer*>(this)->startSmoothing();
1457
1458glEnableClientState(GL_VERTEX_ARRAY);
1459glVertexPointer(3, GL_FLOAT, sizeof(glm::vec3), &rectPoints[0].x);
1460glDrawArrays(currentStyle.bFill ? GL_TRIANGLE_FAN : GL_LINE_LOOP, 0, 4);
1461
1462// use smoothness, if requested:
1463if (currentStyle.smoothing && !currentStyle.bFill) const_cast<ofGLRenderer*>(this)->endSmoothing();
1464
1465}
1466
1467//----------------------------------------------------------
1468void ofGLRenderer::drawTriangle(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3) const{
1469triPoints[0] = {x1,y1,z1};
1470triPoints[1] = {x2,y2,z2};
1471triPoints[2] = {x3,y3,z3};
1472
1473// use smoothness, if requested:
1474if (currentStyle.smoothing && !currentStyle.bFill) const_cast<ofGLRenderer*>(this)->startSmoothing();
1475
1476glEnableClientState(GL_VERTEX_ARRAY);
1477glVertexPointer(3, GL_FLOAT, sizeof(glm::vec3), &triPoints[0].x);
1478glDrawArrays(currentStyle.bFill ? GL_TRIANGLE_FAN : GL_LINE_LOOP, 0, 3);
1479
1480// use smoothness, if requested:
1481if (currentStyle.smoothing && !currentStyle.bFill) const_cast<ofGLRenderer*>(this)->endSmoothing();
1482
1483}
1484
1485//----------------------------------------------------------
1486void ofGLRenderer::drawCircle(float x, float y, float z, float radius) const{
1487const auto & circleCache = circlePolyline.getVertices();
1488for(size_t i=0;i<circleCache.size();i++){
1489circlePoints[i] = {radius*circleCache[i].x+x,radius*circleCache[i].y+y,z};
1490}
1491
1492// use smoothness, if requested:
1493if (currentStyle.smoothing && !currentStyle.bFill) const_cast<ofGLRenderer*>(this)->startSmoothing();
1494
1495glEnableClientState(GL_VERTEX_ARRAY);
1496glVertexPointer(3, GL_FLOAT, sizeof(glm::vec3), &circlePoints[0].x);
1497glDrawArrays(currentStyle.bFill ? GL_TRIANGLE_FAN : GL_LINE_STRIP, 0, circlePoints.size());
1498
1499// use smoothness, if requested:
1500if (currentStyle.smoothing && !currentStyle.bFill) const_cast<ofGLRenderer*>(this)->endSmoothing();
1501
1502}
1503
1504//----------------------------------------------------------
1505void ofGLRenderer::drawEllipse(float x, float y, float z, float width, float height) const{
1506float radiusX = width*0.5;
1507float radiusY = height*0.5;
1508const auto & circleCache = circlePolyline.getVertices();
1509for(size_t i=0;i<circleCache.size();i++){
1510circlePoints[i] = {radiusX*circlePolyline[i].x+x, radiusY*circlePolyline[i].y+y, z};
1511}
1512
1513// use smoothness, if requested:
1514if (currentStyle.smoothing && !currentStyle.bFill) const_cast<ofGLRenderer*>(this)->startSmoothing();
1515
1516glEnableClientState(GL_VERTEX_ARRAY);
1517glVertexPointer(3, GL_FLOAT, sizeof(glm::vec3), &circlePoints[0].x);
1518glDrawArrays(currentStyle.bFill ? GL_TRIANGLE_FAN : GL_LINE_STRIP, 0, circlePoints.size());
1519
1520// use smoothness, if requested:
1521if (currentStyle.smoothing && !currentStyle.bFill) const_cast<ofGLRenderer*>(this)->endSmoothing();
1522
1523}
1524
1525//----------------------------------------------------------
1526void ofGLRenderer::drawString(std::string textString, float x, float y, float z) const{
1527
1528ofGLRenderer * mutThis = const_cast<ofGLRenderer*>(this);
1529float sx = 0;
1530float sy = 0;
1531
1532
1533///////////////////////////
1534// APPLY TRANSFORM / VIEW
1535///////////////////////////
1536//
1537
1538bool hasModelView = false;
1539bool hasProjection = false;
1540bool hasViewport = false;
1541
1542ofRectangle rViewport;
1543bool vflipped = isVFlipped();
1544
1545switch (currentStyle.drawBitmapMode) {
1546
1547case OF_BITMAPMODE_SIMPLE:
1548
1549sx += x;
1550sy += y;
1551break;
1552
1553case OF_BITMAPMODE_SCREEN:
1554
1555hasViewport = true;
1556mutThis->pushView();
1557
1558rViewport = matrixStack.getFullSurfaceViewport();
1559mutThis->viewport(rViewport);
1560
1561mutThis->matrixMode(OF_MATRIX_PROJECTION);
1562mutThis->loadIdentityMatrix();
1563mutThis->matrixMode(OF_MATRIX_MODELVIEW);
1564mutThis->loadIdentityMatrix();
1565
1566mutThis->translate(-1, 1, 0);
1567mutThis->scale(2/rViewport.width, -2/rViewport.height, 1);
1568mutThis->translate(x, rViewport.height - y, 0);
1569vflipped = false;
1570break;
1571
1572case OF_BITMAPMODE_VIEWPORT:
1573
1574rViewport = getCurrentViewport();
1575
1576hasProjection = true;
1577mutThis->matrixMode(OF_MATRIX_PROJECTION);
1578mutThis->pushMatrix();
1579mutThis->loadIdentityMatrix();
1580
1581hasModelView = true;
1582mutThis->matrixMode(OF_MATRIX_MODELVIEW);
1583mutThis->pushMatrix();
1584mutThis->loadIdentityMatrix();
1585
1586mutThis->translate(-1, 1, 0);
1587mutThis->scale(2/rViewport.width, -2/rViewport.height, 1);
1588mutThis->translate(x, rViewport.height - y, 0);
1589vflipped = false;
1590break;
1591
1592case OF_BITMAPMODE_MODEL:
1593
1594hasModelView = true;
1595mutThis->matrixMode(OF_MATRIX_MODELVIEW);
1596mutThis->pushMatrix();
1597
1598mutThis->translate(x, y, z);
1599break;
1600
1601case OF_BITMAPMODE_MODEL_BILLBOARD:
1602{
1603//our aim here is to draw to screen
1604//at the viewport position related
1605//to the world position x,y,z
1606
1607// tig: we want to get the signed normalised screen coordinates (-1,+1) of our point (x,y,z)
1608// that's projection * modelview * point in GLSL multiplication order
1609// then doing the good old (v + 1.0) / 2. to get unsigned normalized screen (0,1) coordinates.
1610// we then multiply x by width and y by height to get window coordinates.
1611
1612// previous implementations used gluProject, which made it incompatible with GLES (and the future)
1613// https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/gluProject.3.html
1614//
1615// this could probably be backported to the GL2 Renderer =)
1616
1617rViewport = getCurrentViewport();
1618
1619glm::mat4 modelview = glm::mat4(1.0), projection = glm::mat4(1.0);
1620glGetFloatv(GL_MODELVIEW_MATRIX, glm::value_ptr(modelview));
1621glGetFloatv(GL_PROJECTION_MATRIX, glm::value_ptr(projection));
1622glm::mat4 mat = matrixStack.getOrientationMatrixInverse() * projection * modelview;
1623glm::vec4 dScreen4 = mat * glm::vec4(x,y,z,1.0);
1624glm::vec3 dScreen = glm::vec3(dScreen4) / dScreen4.w;
1625dScreen += glm::vec3(1.0) ;
1626dScreen *= 0.5;
1627
1628dScreen.x *= rViewport.width;
1629dScreen.x += rViewport.x;
1630
1631dScreen.y *= rViewport.height;
1632dScreen.y += rViewport.y;
1633
1634if (dScreen.z >= 1){
1635return;
1636}
1637
1638
1639hasProjection = true;
1640mutThis->matrixMode(OF_MATRIX_PROJECTION);
1641mutThis->pushMatrix();
1642mutThis->loadIdentityMatrix();
1643
1644hasModelView = true;
1645mutThis->matrixMode(OF_MATRIX_MODELVIEW);
1646mutThis->pushMatrix();
1647mutThis->loadIdentityMatrix();
1648
1649mutThis->translate(-1, -1, 0);
1650
1651mutThis->scale(2/rViewport.width, 2/rViewport.height, 1);
1652
1653mutThis->translate(dScreen.x, dScreen.y, 0);
1654}
1655break;
1656
1657default:
1658break;
1659}
1660// remember the current blend mode so that we can restore it at the end of this method.
1661GLint blend_src, blend_dst;
1662glGetIntegerv( GL_BLEND_SRC, &blend_src );
1663glGetIntegerv( GL_BLEND_DST, &blend_dst );
1664
1665glEnable(GL_BLEND);
1666glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1667#ifndef TARGET_OPENGLES
1668// this temporarily enables alpha testing,
1669// which discards pixels unless their alpha is 1.0f
1670glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
1671glEnable(GL_ALPHA_TEST);
1672glAlphaFunc(GL_GREATER, 0);
1673#endif
1674
1675ofMesh charMesh = bitmapFont.getMesh(textString,sx,sy,currentStyle.drawBitmapMode,vflipped);
1676mutThis->bind(bitmapFont.getTexture(),0);
1677draw(charMesh,OF_MESH_FILL,false,true,false);
1678mutThis->unbind(bitmapFont.getTexture(),0);
1679
1680#ifndef TARGET_OPENGLES
1681glPopAttrib();
1682#endif
1683// restore blendmode
1684glBlendFunc(blend_src, blend_dst);
1685
1686if (hasModelView)
1687mutThis->popMatrix();
1688
1689if (hasProjection)
1690{
1691mutThis->matrixMode(OF_MATRIX_PROJECTION);
1692mutThis->popMatrix();
1693mutThis->matrixMode(OF_MATRIX_MODELVIEW);
1694}
1695
1696if (hasViewport)
1697mutThis->popView();
1698
1699}
1700
1701//----------------------------------------------------------
1702void ofGLRenderer::drawString(const ofTrueTypeFont & font, std::string text, float x, float y) const{
1703ofGLRenderer * mutThis = const_cast<ofGLRenderer*>(this);
1704bool blendEnabled = glIsEnabled(GL_BLEND);
1705GLint blend_src, blend_dst;
1706glGetIntegerv( GL_BLEND_SRC, &blend_src );
1707glGetIntegerv( GL_BLEND_DST, &blend_dst );
1708
1709glEnable(GL_BLEND);
1710glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1711
1712mutThis->bind(font.getFontTexture(),0);
1713draw(font.getStringMesh(text,x,y,isVFlipped()),OF_MESH_FILL);
1714mutThis->unbind(font.getFontTexture(),0);
1715
1716if(!blendEnabled){
1717glDisable(GL_BLEND);
1718}
1719glBlendFunc(blend_src, blend_dst);
1720}
1721
1722//----------------------------------------------------------
1723void ofGLRenderer::enableTextureTarget(const ofTexture & tex, int textureLocation){
1724glActiveTexture(GL_TEXTURE0+textureLocation);
1725glClientActiveTexture(GL_TEXTURE0+textureLocation);
1726glEnable( tex.getTextureData().textureTarget);
1727glBindTexture( tex.getTextureData().textureTarget, (GLuint)tex.getTextureData().textureID);
1728#ifndef TARGET_OPENGLES
1729if(tex.getTextureData().bufferId!=0){
1730glTexBuffer(GL_TEXTURE_BUFFER, tex.getTextureData().glInternalFormat, tex.getTextureData().bufferId);
1731}
1732#endif
1733textureLocationsEnabled.insert(textureLocation);
1734}
1735
1736//----------------------------------------------------------
1737void ofGLRenderer::disableTextureTarget(int textureTarget, int textureLocation){
1738glActiveTexture(GL_TEXTURE0+textureLocation);
1739glBindTexture( textureTarget, 0);
1740glDisable(textureTarget);
1741glActiveTexture(GL_TEXTURE0);
1742textureLocationsEnabled.erase(textureLocation);
1743}
1744
1745//----------------------------------------------------------
1746void ofGLRenderer::setAlphaMaskTex(const ofTexture & tex){
1747enableTextureTarget(tex, 1);
1748alphaMaskTextureTarget = tex.getTextureData().textureTarget;
1749}
1750
1751//----------------------------------------------------------
1752void ofGLRenderer::disableAlphaMask(){
1753disableTextureTarget(alphaMaskTextureTarget,1);
1754}
1755
1756//----------------------------------------------------------
1757void ofGLRenderer::enableLighting(){
1758glEnable(GL_LIGHTING);
1759lightingEnabled = true;
1760setColor(currentStyle.color);
1761// FIXME: we do this so the 3d ofDraw* functions work with lighting
1762// but if someone enables it between ofEnableLighting it'll be disabled
1763// on ofDisableLighting. by now it seems the best option to not loose
1764// performance when drawing lots of primitives
1765normalsEnabled = glIsEnabled( GL_NORMALIZE );
1766glEnable(GL_NORMALIZE);
1767
1768int matrixMode;
1769glGetIntegerv(GL_MATRIX_MODE,&matrixMode);
1770glMatrixMode(GL_MODELVIEW);
1771glPushMatrix();
1772glLoadMatrixf(glm::value_ptr(matrixStack.getViewMatrix()));
1773for(size_t i=0;i<ofLightsData().size();i++){
1774std::shared_ptr<ofLight::Data> lightData = ofLightsData()[i].lock();
1775if(lightData && lightData->isEnabled){
1776glLightfv(GL_LIGHT0 + lightData->glIndex, GL_POSITION, &lightData->position.x);
1777if(lightData->lightType == OF_LIGHT_SPOT || lightData->lightType == OF_LIGHT_AREA) {
1778glLightfv(GL_LIGHT0 + lightData->glIndex, GL_SPOT_DIRECTION, &lightData->direction.x);
1779}
1780}
1781}
1782glPopMatrix();
1783glMatrixMode(matrixMode);
1784}
1785
1786//----------------------------------------------------------
1787void ofGLRenderer::disableLighting(){
1788glDisable(GL_LIGHTING);
1789if(!normalsEnabled){
1790glDisable(GL_NORMALIZE);
1791}
1792lightingEnabled = false;
1793}
1794
1795//----------------------------------------------------------
1796void ofGLRenderer::enableSeparateSpecularLight(){
1797#ifndef TARGET_OPENGLES
1798glLightModeli (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);
1799#endif
1800}
1801
1802//----------------------------------------------------------
1803void ofGLRenderer::disableSeparateSpecularLight(){
1804#ifndef TARGET_OPENGLES
1805glLightModeli (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR);
1806#endif
1807}
1808
1809//----------------------------------------------------------
1810bool ofGLRenderer::getLightingEnabled(){
1811return glIsEnabled(GL_LIGHTING);
1812}
1813
1814//----------------------------------------------------------
1815void ofGLRenderer::setSmoothLighting(bool b){
1816if (b) glShadeModel(GL_SMOOTH);
1817else glShadeModel(GL_FLAT);
1818}
1819
1820//----------------------------------------------------------
1821void ofGLRenderer::setGlobalAmbientColor(const ofColor& c){
1822GLfloat cc[] = {c.r/255.f, c.g/255.f, c.b/255.f, c.a/255.f};
1823glLightModelfv(GL_LIGHT_MODEL_AMBIENT, cc);
1824}
1825
1826//----------------------------------------------------------
1827void ofGLRenderer::enableLight(int lightIndex){
1828enableLighting();
1829glEnable(GL_LIGHT0 + lightIndex);
1830}
1831
1832//----------------------------------------------------------
1833void ofGLRenderer::disableLight(int lightIndex){
1834if(lightIndex!=-1) {
1835glDisable(GL_LIGHT0 + lightIndex);
1836}
1837}
1838
1839//----------------------------------------------------------
1840void ofGLRenderer::setLightSpotlightCutOff(int lightIndex, float spotCutOff){
1841glLightf(GL_LIGHT0 + lightIndex, GL_SPOT_CUTOFF, spotCutOff );
1842}
1843
1844//----------------------------------------------------------
1845void ofGLRenderer::setLightSpotConcentration(int lightIndex, float exponent){
1846glLightf(GL_LIGHT0 + lightIndex, GL_SPOT_EXPONENT, exponent);
1847}
1848
1849//----------------------------------------------------------
1850void ofGLRenderer::setLightAttenuation(int lightIndex, float constant, float linear, float quadratic ){
1851if(lightIndex==-1) return;
1852glLightf(GL_LIGHT0 + lightIndex, GL_CONSTANT_ATTENUATION, constant);
1853glLightf(GL_LIGHT0 + lightIndex, GL_LINEAR_ATTENUATION, linear);
1854glLightf(GL_LIGHT0 + lightIndex, GL_QUADRATIC_ATTENUATION, quadratic);
1855}
1856
1857//----------------------------------------------------------
1858void ofGLRenderer::setLightAmbientColor(int lightIndex, const ofFloatColor& c){
1859if(lightIndex==-1) return;
1860glLightfv(GL_LIGHT0 + lightIndex, GL_AMBIENT, &c.r);
1861}
1862
1863//----------------------------------------------------------
1864void ofGLRenderer::setLightDiffuseColor(int lightIndex, const ofFloatColor& c){
1865if(lightIndex==-1) return;
1866glLightfv(GL_LIGHT0 + lightIndex, GL_DIFFUSE, &c.r);
1867}
1868
1869//----------------------------------------------------------
1870void ofGLRenderer::setLightSpecularColor(int lightIndex, const ofFloatColor& c){
1871if(lightIndex==-1) return;
1872glLightfv(GL_LIGHT0 + lightIndex, GL_SPECULAR, &c.r);
1873}
1874
1875//----------------------------------------------------------
1876void ofGLRenderer::setLightPosition(int lightIndex, const glm::vec4 & position){
1877if(lightIndex==-1) return;
1878int matrixMode;
1879glGetIntegerv(GL_MATRIX_MODE,&matrixMode);
1880glMatrixMode(GL_MODELVIEW);
1881glPushMatrix();
1882glLoadMatrixf(glm::value_ptr(matrixStack.getViewMatrix()));
1883glLightfv(GL_LIGHT0 + lightIndex, GL_POSITION, glm::value_ptr(position));
1884glPopMatrix();
1885glMatrixMode(matrixMode);
1886}
1887
1888//----------------------------------------------------------
1889void ofGLRenderer::setLightSpotDirection(int lightIndex, const glm::vec4 & direction){
1890if(lightIndex==-1) return;
1891int matrixMode;
1892glGetIntegerv(GL_MATRIX_MODE,&matrixMode);
1893glMatrixMode(GL_MODELVIEW);
1894glPushMatrix();
1895glLoadMatrixf(glm::value_ptr(matrixStack.getViewMatrix()));
1896glLightfv(GL_LIGHT0 + lightIndex, GL_SPOT_DIRECTION, glm::value_ptr(direction));
1897glPopMatrix();
1898glMatrixMode(matrixMode);
1899}
1900
1901//----------------------------------------------------------
1902int ofGLRenderer::getGLVersionMajor(){
1903#ifdef TARGET_OPENGLES
1904return 1;
1905#else
1906return 2;
1907#endif
1908}
1909
1910//----------------------------------------------------------
1911int ofGLRenderer::getGLVersionMinor(){
1912#ifdef TARGET_OPENGLES
1913return 0;
1914#else
1915return 1;
1916#endif
1917}
1918
1919//----------------------------------------------------------
1920void ofGLRenderer::saveFullViewport(ofPixels & pixels){
1921ofRectangle v = getCurrentViewport();
1922saveScreen(v.x,v.y,v.width,v.height,pixels);
1923}
1924
1925//----------------------------------------------------------
1926void ofGLRenderer::saveScreen(int x, int y, int w, int h, ofPixels & pixels){
1927int sh = getViewportHeight();
1928
1929
1930#ifndef TARGET_OPENGLES
1931if(isVFlipped()){
1932y = sh - y;
1933y -= h; // top, bottom issues
1934}
1935auto pixelFormat = OF_PIXELS_BGRA;
1936pixels.allocate(w, h, pixelFormat);
1937auto glFormat = ofGetGLFormat(pixels);
1938
1939
1940glReadPixels(x, y, w, h, glFormat, GL_UNSIGNED_BYTE, pixels.begin()); // read the memory....
1941pixels.mirror(true, false);
1942#else
1943
1944int sw = getViewportWidth();
1945int numPixels = w*h;
1946if( numPixels == 0 ){
1947ofLogError("ofImage") << "grabScreen(): unable to grab screen, image width and/or height are 0: " << w << "x" << h;
1948return;
1949}
1950pixels.allocate(w, h, OF_PIXELS_RGBA);
1951
1952switch(matrixStack.getOrientation()){
1953case OF_ORIENTATION_UNKNOWN:
1954case OF_ORIENTATION_DEFAULT:
1955
1956if(isVFlipped()){
1957y = sh - y; // screen is flipped vertically.
1958y -= h;
1959}
1960
1961glPixelStorei(GL_PACK_ALIGNMENT, 1);
1962glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels.getData());
1963pixels.mirror(true,false);
1964break;
1965case OF_ORIENTATION_180:
1966
1967if(isVFlipped()){
1968x = sw - x; // screen is flipped horizontally.
1969x -= w;
1970}
1971
1972glPixelStorei(GL_PACK_ALIGNMENT, 1);
1973glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels.getData());
1974pixels.mirror(false,true);
1975break;
1976case OF_ORIENTATION_90_RIGHT:
1977std::swap(w,h);
1978std::swap(x,y);
1979if(!isVFlipped()){
1980x = sw - x; // screen is flipped horizontally.
1981x -= w;
1982
1983y = sh - y; // screen is flipped vertically.
1984y -= h;
1985}
1986
1987glPixelStorei(GL_PACK_ALIGNMENT, 1);
1988glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels.getData());
1989pixels.mirror(true,true);
1990break;
1991case OF_ORIENTATION_90_LEFT:
1992std::swap(w, h);
1993std::swap(x, y);
1994if(isVFlipped()){
1995x = sw - x; // screen is flipped horizontally.
1996x -= w;
1997
1998y = sh - y; // screen is flipped vertically.
1999y -= h;
2000}
2001
2002glPixelStorei(GL_PACK_ALIGNMENT, 1);
2003glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels.getData());
2004pixels.mirror(true,true);
2005break;
2006}
2007
2008#endif
2009}
2010
2011//----------------------------------------------------------
2012const of3dGraphics & ofGLRenderer::get3dGraphics() const{
2013return graphics3d;
2014}
2015
2016//----------------------------------------------------------
2017of3dGraphics & ofGLRenderer::get3dGraphics(){
2018return graphics3d;
2019}
2020