framework2
2825 строк · 89.2 Кб
1#include "ofGLProgrammableRenderer.h"
2#include "ofMesh.h"
3#include "ofPath.h"
4#include "ofBitmapFont.h"
5#include "ofGLUtils.h"
6#include "ofImage.h"
7#include "ofFbo.h"
8#include "ofVboMesh.h"
9#include "of3dPrimitives.h"
10#include "ofLight.h"
11#include "ofMaterialBaseTypes.h"
12#include "ofCamera.h"
13#include "ofTrueTypeFont.h"
14#include "ofNode.h"
15#include "ofVideoBaseTypes.h"
16
17using std::vector;
18using std::string;
19using std::swap;
20
21static const string MODEL_MATRIX_UNIFORM="modelMatrix";
22static const string VIEW_MATRIX_UNIFORM="viewMatrix";
23static const string MODELVIEW_MATRIX_UNIFORM="modelViewMatrix";
24static const string PROJECTION_MATRIX_UNIFORM="projectionMatrix";
25static const string MODELVIEW_PROJECTION_MATRIX_UNIFORM="modelViewProjectionMatrix";
26static const string TEXTURE_MATRIX_UNIFORM="textureMatrix";
27static const string COLOR_UNIFORM="globalColor";
28
29static const string USE_TEXTURE_UNIFORM="usingTexture";
30static const string USE_COLORS_UNIFORM="usingColors";
31static const string BITMAP_STRING_UNIFORM="bitmapText";
32
33
34const string ofGLProgrammableRenderer::TYPE="ProgrammableGL";
35static bool programmableRendererCreated = false;
36
37bool ofIsGLProgrammableRenderer(){
38return programmableRendererCreated;
39}
40
41
42//----------------------------------------------------------
43ofGLProgrammableRenderer::ofGLProgrammableRenderer(const ofAppBaseWindow * _window)
44:matrixStack(_window)
45,graphics3d(this)
46{
47programmableRendererCreated = true;
48bBackgroundAuto = true;
49
50lineMesh.getVertices().resize(2);
51lineMesh.setMode(OF_PRIMITIVE_LINES);
52triangleMesh.getVertices().resize(3);
53rectMesh.getVertices().resize(4);
54
55bitmapStringEnabled = false;
56verticesEnabled = true;
57colorsEnabled = false;
58texCoordsEnabled = false;
59normalsEnabled = false;
60settingDefaultShader = false;
61usingVideoShader = false;
62usingCustomShader = false;
63
64wrongUseLoggedOnce = false;
65
66uniqueShader = false;
67
68currentShader = nullptr;
69
70currentTextureTarget = OF_NO_TEXTURE;
71currentMaterial = nullptr;
72alphaMaskTextureTarget = OF_NO_TEXTURE;
73
74currentShadow = nullptr;
75bIsShadowDepthPass = false;
76
77major = 3;
78minor = 2;
79window = _window;
80
81currentFramebufferId = 0;
82defaultFramebufferId = 0;
83path.setMode(ofPath::POLYLINES);
84path.setUseShapeColor(false);
85currentEyePos = {0.f,0.f,0.f};
86}
87
88//----------------------------------------------------------
89void ofGLProgrammableRenderer::startRender() {
90currentFramebufferId = defaultFramebufferId;
91framebufferIdStack.push_back(defaultFramebufferId);
92matrixStack.setRenderSurface(*window);
93beginDefaultShader();
94viewport();
95// to do non auto clear on PC for now - we do something like "single" buffering --
96// it's not that pretty but it work for the most part
97
98#ifdef TARGET_WIN32
99if (getBackgroundAuto() == false){
100glDrawBuffer (GL_FRONT);
101}
102#endif
103
104if ( getBackgroundAuto() ){// || ofGetFrameNum() < 3){
105background(currentStyle.bgColor);
106}
107}
108
109//----------------------------------------------------------
110void ofGLProgrammableRenderer::finishRender() {
111if (!uniqueShader) {
112glUseProgram(0);
113if(!usingCustomShader) currentShader = nullptr;
114}
115matrixStack.clearStacks();
116framebufferIdStack.clear();
117}
118
119//----------------------------------------------------------
120void ofGLProgrammableRenderer::draw(const ofMesh & vertexData, ofPolyRenderMode renderType, bool useColors, bool useTextures, bool useNormals) const{
121if (vertexData.getVertices().empty()) return;
122
123
124// tig: note that for GL3+ we use glPolygonMode to draw wireframes or filled meshes, and not the primitive mode.
125// the reason is not purely aesthetic, but more conformant with the behaviour of ofGLRenderer. Whereas
126// gles2.0 doesn't allow for a polygonmode.
127// Also gles2 still supports vertex array syntax for uploading data to attributes and it seems to be faster than
128// vbo's for meshes that are updated frequently so let's use that instead
129
130//if (bSmoothHinted) startSmoothing();
131
132#if defined(TARGET_OPENGLES) && !defined(TARGET_EMSCRIPTEN)
133glEnableVertexAttribArray(ofShader::POSITION_ATTRIBUTE);
134glVertexAttribPointer(ofShader::POSITION_ATTRIBUTE, 3, GL_FLOAT, GL_FALSE, sizeof(typename ofMesh::VertexType), vertexData.getVerticesPointer());
135
136useNormals &= (vertexData.getNumNormals()>0);
137if(useNormals){
138glEnableVertexAttribArray(ofShader::NORMAL_ATTRIBUTE);
139glVertexAttribPointer(ofShader::NORMAL_ATTRIBUTE, 3, GL_FLOAT, GL_TRUE, sizeof(typename ofMesh::NormalType), vertexData.getNormalsPointer());
140}else{
141glDisableVertexAttribArray(ofShader::NORMAL_ATTRIBUTE);
142}
143
144useColors &= (vertexData.getNumColors()>0);
145if(useColors){
146glEnableVertexAttribArray(ofShader::COLOR_ATTRIBUTE);
147glVertexAttribPointer(ofShader::COLOR_ATTRIBUTE, 4,GL_FLOAT, GL_FALSE, sizeof(ofFloatColor), vertexData.getColorsPointer());
148}else{
149glDisableVertexAttribArray(ofShader::COLOR_ATTRIBUTE);
150}
151
152useTextures &= (vertexData.getNumTexCoords()>0);
153if(useTextures){
154glEnableVertexAttribArray(ofShader::TEXCOORD_ATTRIBUTE);
155glVertexAttribPointer(ofShader::TEXCOORD_ATTRIBUTE,2, GL_FLOAT, GL_FALSE, sizeof(typename ofMesh::TexCoordType), vertexData.getTexCoordsPointer());
156}else{
157glDisableVertexAttribArray(ofShader::TEXCOORD_ATTRIBUTE);
158}
159
160
161const_cast<ofGLProgrammableRenderer*>(this)->setAttributes(true,useColors,useTextures,useNormals);
162
163GLenum drawMode;
164switch(renderType){
165case OF_MESH_POINTS:
166drawMode = GL_POINTS;
167break;
168case OF_MESH_WIREFRAME:
169drawMode = GL_LINES;
170break;
171case OF_MESH_FILL:
172drawMode = ofGetGLPrimitiveMode(vertexData.getMode());
173break;
174default:
175drawMode = ofGetGLPrimitiveMode(vertexData.getMode());
176break;
177}
178
179if(vertexData.getNumIndices()){
180glDrawElements(drawMode, vertexData.getNumIndices(),GL_UNSIGNED_SHORT,vertexData.getIndexPointer());
181}else{
182glDrawArrays(drawMode, 0, vertexData.getNumVertices());
183}
184#else
185
186
187#ifndef TARGET_OPENGLES
188meshVbo.setMesh(vertexData, GL_STREAM_DRAW, useColors, useTextures, useNormals);
189glPolygonMode(GL_FRONT_AND_BACK, ofGetGLPolyMode(renderType));
190GLenum drawMode = ofGetGLPrimitiveMode(vertexData.getMode());
191#else
192meshVbo.setMesh(vertexData, GL_STATIC_DRAW, useColors, useTextures, useNormals);
193GLenum drawMode;
194switch(renderType){
195case OF_MESH_POINTS:
196drawMode = GL_POINTS;
197break;
198case OF_MESH_WIREFRAME:
199drawMode = GL_LINE_STRIP;
200break;
201case OF_MESH_FILL:
202drawMode = ofGetGLPrimitiveMode(vertexData.getMode());
203break;
204default:
205drawMode = ofGetGLPrimitiveMode(vertexData.getMode());
206break;
207}
208#endif
209if(meshVbo.getUsingIndices()) {
210drawElements(meshVbo,drawMode, meshVbo.getNumIndices());
211} else {
212draw(meshVbo, drawMode, 0, vertexData.getNumVertices());
213}
214
215// tig: note further that we could glGet() and store the current polygon mode, but don't, since that would
216// infer a massive performance hit. instead, we revert the glPolygonMode to mirror the current ofFill state
217// after we're finished drawing, following the principle of least surprise.
218// ideally the glPolygonMode (or the polygon draw mode) should be part of ofStyle so that we can keep track
219// of its state on the client side...
220
221#ifndef TARGET_OPENGLES
222glPolygonMode(GL_FRONT_AND_BACK, currentStyle.bFill ? GL_FILL : GL_LINE);
223#endif
224
225#endif
226
227//if (bSmoothHinted) endSmoothing();
228}
229
230//----------------------------------------------------------
231void ofGLProgrammableRenderer::draw(const ofVboMesh & mesh, ofPolyRenderMode renderType) const{
232drawInstanced(mesh,renderType,1);
233}
234
235//----------------------------------------------------------
236void ofGLProgrammableRenderer::drawInstanced(const ofVboMesh & mesh, ofPolyRenderMode renderType, int primCount) const{
237if(mesh.getNumVertices()==0) return;
238GLuint mode = ofGetGLPrimitiveMode(mesh.getMode());
239#ifndef TARGET_OPENGLES
240glPolygonMode(GL_FRONT_AND_BACK, ofGetGLPolyMode(renderType));
241if(mesh.getNumIndices() && renderType!=OF_MESH_POINTS){
242if (primCount <= 1) {
243drawElements(mesh.getVbo(),mode,mesh.getNumIndices());
244} else {
245drawElementsInstanced(mesh.getVbo(),mode,mesh.getNumIndices(),primCount);
246}
247}else{
248if (primCount <= 1) {
249draw(mesh.getVbo(),mode,0,mesh.getNumVertices());
250} else {
251drawInstanced(mesh.getVbo(),mode,0,mesh.getNumVertices(),primCount);
252}
253}
254
255// tig: note further that we could glGet() and store the current polygon mode, but don't, since that would
256// infer a massive performance hit. instead, we revert the glPolygonMode to mirror the current ofFill state
257// after we're finished drawing, following the principle of least surprise.
258// ideally the glPolygonMode (or the polygon draw mode) should be part of ofStyle so that we can keep track
259// of its state on the client side...
260
261glPolygonMode(GL_FRONT_AND_BACK, currentStyle.bFill ? GL_FILL : GL_LINE);
262#else
263if(renderType == OF_MESH_POINTS){
264draw(mesh.getVbo(),GL_POINTS,0,mesh.getNumVertices());
265}else if(renderType == OF_MESH_WIREFRAME){
266if(mesh.getNumIndices()){
267drawElements(mesh.getVbo(),GL_LINES,mesh.getNumIndices());
268}else{
269draw(mesh.getVbo(),GL_LINES,0,mesh.getNumVertices());
270}
271}else{
272if(mesh.getNumIndices()){
273drawElements(mesh.getVbo(),mode,mesh.getNumIndices());
274}else{
275draw(mesh.getVbo(),mode,0,mesh.getNumVertices());
276}
277}
278#endif
279}
280
281//----------------------------------------------------------
282void ofGLProgrammableRenderer::draw( const of3dPrimitive& model, ofPolyRenderMode renderType) const {
283const_cast<ofGLProgrammableRenderer*>(this)->pushMatrix();
284const_cast<ofGLProgrammableRenderer*>(this)->multMatrix(model.getGlobalTransformMatrix());
285if(model.isUsingVbo()){
286draw(static_cast<const ofVboMesh&>(model.getMesh()),renderType);
287}else{
288draw(model.getMesh(),renderType);
289}
290const_cast<ofGLProgrammableRenderer*>(this)->popMatrix();
291}
292
293//----------------------------------------------------------
294void ofGLProgrammableRenderer::draw(const ofNode& node) const{
295const_cast<ofGLProgrammableRenderer*>(this)->pushMatrix();
296const_cast<ofGLProgrammableRenderer*>(this)->multMatrix(node.getGlobalTransformMatrix());
297node.customDraw(this);
298const_cast<ofGLProgrammableRenderer*>(this)->popMatrix();
299}
300
301//----------------------------------------------------------
302void ofGLProgrammableRenderer::draw(const ofPolyline & poly) const{
303if(poly.getVertices().empty()) return;
304
305// use smoothness, if requested:
306//if (bSmoothHinted) startSmoothing();
307
308#if defined( TARGET_OPENGLES ) && !defined(TARGET_EMSCRIPTEN)
309
310glEnableVertexAttribArray(ofShader::POSITION_ATTRIBUTE);
311glVertexAttribPointer(ofShader::POSITION_ATTRIBUTE, 3, GL_FLOAT, GL_FALSE, sizeof(typename ofPolyline::VertexType), &poly[0]);
312
313const_cast<ofGLProgrammableRenderer*>(this)->setAttributes(true,false,false,false);
314
315GLenum drawMode = poly.isClosed()?GL_LINE_LOOP:GL_LINE_STRIP;
316
317glDrawArrays(drawMode, 0, poly.size());
318
319#else
320
321meshVbo.setVertexData(&poly.getVertices()[0], poly.size(), GL_DYNAMIC_DRAW);
322meshVbo.draw(poly.isClosed()?GL_LINE_LOOP:GL_LINE_STRIP, 0, poly.size());
323
324#endif
325// use smoothness, if requested:
326//if (bSmoothHinted) endSmoothing();
327}
328
329//----------------------------------------------------------
330void ofGLProgrammableRenderer::draw(const ofPath & shape) const{
331ofColor prevColor;
332if(shape.getUseShapeColor()){
333prevColor = currentStyle.color;
334}
335ofGLProgrammableRenderer * mut_this = const_cast<ofGLProgrammableRenderer*>(this);
336if(shape.isFilled()){
337const ofMesh & mesh = shape.getTessellation();
338if(shape.getUseShapeColor()){
339mut_this->setColor( shape.getFillColor(),shape.getFillColor().a);
340}
341draw(mesh,OF_MESH_FILL);
342}
343if(shape.hasOutline()){
344float lineWidth = currentStyle.lineWidth;
345if(shape.getUseShapeColor()){
346mut_this->setColor( shape.getStrokeColor(), shape.getStrokeColor().a);
347}
348mut_this->setLineWidth( shape.getStrokeWidth() );
349const vector<ofPolyline> & outlines = shape.getOutline();
350for(int i=0; i<(int)outlines.size(); i++)
351draw(outlines[i]);
352mut_this->setLineWidth(lineWidth);
353}
354if(shape.getUseShapeColor()){
355mut_this->setColor(prevColor);
356}
357}
358
359//----------------------------------------------------------
360void ofGLProgrammableRenderer::draw(const ofImage & image, float x, float y, float z, float w, float h, float sx, float sy, float sw, float sh) const{
361if(image.isUsingTexture()){
362const_cast<ofGLProgrammableRenderer*>(this)->setAttributes(true,false,true,false);
363const ofTexture& tex = image.getTexture();
364if(tex.isAllocated()) {
365const_cast<ofGLProgrammableRenderer*>(this)->bind(tex,0);
366draw(tex.getMeshForSubsection(x,y,z,w,h,sx,sy,sw,sh,isVFlipped(),currentStyle.rectMode),OF_MESH_FILL,false,true,false);
367const_cast<ofGLProgrammableRenderer*>(this)->unbind(tex,0);
368} else {
369ofLogWarning("ofGLProgrammableRenderer") << "draw(): texture is not allocated";
370}
371}
372}
373
374//----------------------------------------------------------
375void ofGLProgrammableRenderer::draw(const ofFloatImage & image, float x, float y, float z, float w, float h, float sx, float sy, float sw, float sh) const{
376if(image.isUsingTexture()){
377const_cast<ofGLProgrammableRenderer*>(this)->setAttributes(true,false,true,false);
378const ofTexture& tex = image.getTexture();
379if(tex.isAllocated()) {
380const_cast<ofGLProgrammableRenderer*>(this)->bind(tex,0);
381draw(tex.getMeshForSubsection(x,y,z,w,h,sx,sy,sw,sh,isVFlipped(),currentStyle.rectMode),OF_MESH_FILL,false,true,false);
382const_cast<ofGLProgrammableRenderer*>(this)->unbind(tex,0);
383} else {
384ofLogWarning("ofGLProgrammableRenderer") << "draw(): texture is not allocated";
385}
386}
387}
388
389//----------------------------------------------------------
390void ofGLProgrammableRenderer::draw(const ofShortImage & image, float x, float y, float z, float w, float h, float sx, float sy, float sw, float sh) const{
391if(image.isUsingTexture()){
392const_cast<ofGLProgrammableRenderer*>(this)->setAttributes(true,false,true,false);
393const ofTexture& tex = image.getTexture();
394if(tex.isAllocated()) {
395const_cast<ofGLProgrammableRenderer*>(this)->bind(tex,0);
396draw(tex.getMeshForSubsection(x,y,z,w,h,sx,sy,sw,sh,isVFlipped(),currentStyle.rectMode),OF_MESH_FILL,false,true,false);
397const_cast<ofGLProgrammableRenderer*>(this)->unbind(tex,0);
398} else {
399ofLogWarning("ofGLProgrammableRenderer") << "draw(): texture is not allocated";
400}
401}
402}
403
404//----------------------------------------------------------
405void ofGLProgrammableRenderer::draw(const ofTexture & tex, float x, float y, float z, float w, float h, float sx, float sy, float sw, float sh) const{
406const_cast<ofGLProgrammableRenderer*>(this)->setAttributes(true,false,true,false);
407if(tex.isAllocated()) {
408const_cast<ofGLProgrammableRenderer*>(this)->bind(tex,0);
409draw(tex.getMeshForSubsection(x,y,z,w,h,sx,sy,sw,sh,isVFlipped(),currentStyle.rectMode),OF_MESH_FILL,false,true,false);
410const_cast<ofGLProgrammableRenderer*>(this)->unbind(tex,0);
411} else {
412ofLogWarning("ofGLProgrammableRenderer") << "draw(): texture is not allocated";
413}
414}
415
416//----------------------------------------------------------
417void ofGLProgrammableRenderer::draw(const ofBaseVideoDraws & video, float x, float y, float w, float h) const{
418if(!video.isInitialized() || !video.isUsingTexture() || video.getTexturePlanes().empty()){
419return;
420}
421const_cast<ofGLProgrammableRenderer*>(this)->bind(video);
422draw(video.getTexture().getMeshForSubsection(x,y,0,w,h,0,0,video.getWidth(),video.getHeight(),isVFlipped(),currentStyle.rectMode),OF_MESH_FILL,false,true,false);
423const_cast<ofGLProgrammableRenderer*>(this)->unbind(video);
424}
425
426//----------------------------------------------------------
427void ofGLProgrammableRenderer::draw(const ofVbo & vbo, GLuint drawMode, int first, int total) const{
428if(vbo.getUsingVerts()) {
429vbo.bind();
430const_cast<ofGLProgrammableRenderer*>(this)->setAttributes(vbo.getUsingVerts(),vbo.getUsingColors(),vbo.getUsingTexCoords(),vbo.getUsingNormals());
431glDrawArrays(drawMode, first, total);
432vbo.unbind();
433}
434}
435
436//----------------------------------------------------------
437void ofGLProgrammableRenderer::drawElements(const ofVbo & vbo, GLuint drawMode, int amt, int offsetelements) const{
438if(vbo.getUsingVerts()) {
439vbo.bind();
440const_cast<ofGLProgrammableRenderer*>(this)->setAttributes(vbo.getUsingVerts(),vbo.getUsingColors(),vbo.getUsingTexCoords(),vbo.getUsingNormals());
441#ifdef TARGET_OPENGLES
442glDrawElements(drawMode, amt, GL_UNSIGNED_SHORT, (void*)(sizeof(ofIndexType) * offsetelements));
443#else
444glDrawElements(drawMode, amt, GL_UNSIGNED_INT, (void*)(sizeof(ofIndexType) * offsetelements));
445#endif
446vbo.unbind();
447}
448}
449
450//----------------------------------------------------------
451void ofGLProgrammableRenderer::drawInstanced(const ofVbo & vbo, GLuint drawMode, int first, int total, int primCount) const{
452if(vbo.getUsingVerts()) {
453vbo.bind();
454const_cast<ofGLProgrammableRenderer*>(this)->setAttributes(vbo.getUsingVerts(),vbo.getUsingColors(),vbo.getUsingTexCoords(),vbo.getUsingNormals());
455#ifdef TARGET_OPENGLES
456// todo: activate instancing once OPENGL ES supports instancing, starting with version 3.0
457// unfortunately there is currently no easy way within oF to query the current OpenGL version.
458// https://www.khronos.org/opengles/sdk/docs/man3/xhtml/glDrawElementsInstanced.xml
459ofLogWarning("ofVbo") << "drawInstanced(): hardware instancing is not supported on OpenGL ES < 3.0";
460// glDrawArraysInstanced(drawMode, first, total, primCount);
461#else
462glDrawArraysInstanced(drawMode, first, total, primCount);
463#endif
464vbo.unbind();
465}
466}
467
468//----------------------------------------------------------
469void ofGLProgrammableRenderer::drawElementsInstanced(const ofVbo & vbo, GLuint drawMode, int amt, int primCount) const{
470if(vbo.getUsingVerts()) {
471vbo.bind();
472const_cast<ofGLProgrammableRenderer*>(this)->setAttributes(vbo.getUsingVerts(),vbo.getUsingColors(),vbo.getUsingTexCoords(),vbo.getUsingNormals());
473#ifdef TARGET_OPENGLES
474// todo: activate instancing once OPENGL ES supports instancing, starting with version 3.0
475// unfortunately there is currently no easy way within oF to query the current OpenGL version.
476// https://www.khronos.org/opengles/sdk/docs/man3/xhtml/glDrawElementsInstanced.xml
477ofLogWarning("ofVbo") << "drawElementsInstanced(): hardware instancing is not supported on OpenGL ES < 3.0";
478// glDrawElementsInstanced(drawMode, amt, GL_UNSIGNED_SHORT, nullptr, primCount);
479#else
480glDrawElementsInstanced(drawMode, amt, GL_UNSIGNED_INT, nullptr, primCount);
481#endif
482vbo.unbind();
483}
484}
485
486//----------------------------------------------------------
487ofPath & ofGLProgrammableRenderer::getPath(){
488return path;
489}
490
491//----------------------------------------------------------
492void ofGLProgrammableRenderer::bind(const ofBaseVideoDraws & video){
493if(!video.isInitialized() || !video.isUsingTexture() || video.getTexturePlanes().empty()){
494return;
495}
496const ofShader * shader = nullptr;
497if(!usingCustomShader){
498shader = getVideoShader(video);
499if(shader){
500bind(*shader);
501setVideoShaderUniforms(video,*shader);
502usingVideoShader = true;
503}
504}
505
506if(!usingVideoShader){
507bind(video.getTexture(),0);
508}
509}
510
511//----------------------------------------------------------
512void ofGLProgrammableRenderer::unbind(const ofBaseVideoDraws & video){
513if(!video.isInitialized() || !video.isUsingTexture() || video.getTexturePlanes().empty()){
514return;
515}
516if(usingVideoShader){
517unbind(*currentShader);
518}else{
519unbind(video.getTexture(),0);
520}
521usingVideoShader = false;
522}
523
524//----------------------------------------------------------
525void ofGLProgrammableRenderer::pushView() {
526matrixStack.pushView();
527}
528
529//----------------------------------------------------------
530void ofGLProgrammableRenderer::popView() {
531matrixStack.popView();
532uploadMatrices();
533viewport(matrixStack.getCurrentViewport());
534}
535
536//----------------------------------------------------------
537void ofGLProgrammableRenderer::viewport(ofRectangle viewport_){
538viewport(viewport_.x,viewport_.y,viewport_.width,viewport_.height,isVFlipped());
539}
540
541//----------------------------------------------------------
542void ofGLProgrammableRenderer::viewport(float x, float y, float width, float height, bool vflip) {
543matrixStack.viewport(x,y,width,height,vflip);
544ofRectangle nativeViewport = matrixStack.getNativeViewport();
545glViewport(nativeViewport.x,nativeViewport.y,nativeViewport.width,nativeViewport.height);
546}
547
548//----------------------------------------------------------
549ofRectangle ofGLProgrammableRenderer::getCurrentViewport() const{
550return matrixStack.getCurrentViewport();
551}
552
553//----------------------------------------------------------
554ofRectangle ofGLProgrammableRenderer::getNativeViewport() const{
555return matrixStack.getNativeViewport();
556}
557
558//----------------------------------------------------------
559int ofGLProgrammableRenderer::getViewportWidth() const{
560return getCurrentViewport().width;
561}
562
563//----------------------------------------------------------
564int ofGLProgrammableRenderer::getViewportHeight() const{
565return getCurrentViewport().height;
566}
567
568//----------------------------------------------------------
569bool ofGLProgrammableRenderer::isVFlipped() const{
570return matrixStack.isVFlipped();
571}
572
573//----------------------------------------------------------
574void ofGLProgrammableRenderer::setCoordHandedness(ofHandednessType handedness) {
575;
576}
577
578//----------------------------------------------------------
579ofHandednessType ofGLProgrammableRenderer::getCoordHandedness() const{
580return matrixStack.getHandedness();
581}
582
583//----------------------------------------------------------
584void ofGLProgrammableRenderer::setOrientation(ofOrientation orientation, bool vFlip){
585matrixStack.setOrientation(orientation,vFlip);
586uploadMatrices();
587
588}
589
590//----------------------------------------------------------
591void ofGLProgrammableRenderer::setupScreenPerspective(float width, float height, float fov, float nearDist, float farDist) {
592float viewW, viewH;
593if(width<0 || height<0){
594ofRectangle currentViewport = getCurrentViewport();
595
596viewW = currentViewport.width;
597viewH = currentViewport.height;
598}else{
599viewW = width;
600viewH = height;
601}
602
603float eyeX = viewW / 2;
604float eyeY = viewH / 2;
605float halfFov = glm::pi<float>() * fov / 360.0f;
606float theTan = tanf(halfFov);
607float dist = eyeY / theTan;
608float aspect = (float) viewW / viewH;
609
610if(nearDist == 0) nearDist = dist / 10.0f;
611if(farDist == 0) farDist = dist * 10.0f;
612
613
614matrixMode(OF_MATRIX_PROJECTION);
615auto persp = glm::perspective(ofDegToRad(fov), aspect, nearDist, farDist);
616loadMatrix( persp );
617
618matrixMode(OF_MATRIX_MODELVIEW);
619auto lookAt = glm::lookAt( glm::vec3{eyeX, eyeY, dist}, glm::vec3{eyeX, eyeY, 0.f}, glm::vec3{0.f, 1.f, 0.f} );
620loadViewMatrix(lookAt);
621
622currentEyePos = glm::vec3{eyeX, eyeY, dist};
623
624}
625
626//----------------------------------------------------------
627void ofGLProgrammableRenderer::setupScreenOrtho(float width, float height, float nearDist, float farDist) {
628float viewW, viewH;
629if(width<0 || height<0){
630ofRectangle currentViewport = getCurrentViewport();
631
632viewW = currentViewport.width;
633viewH = currentViewport.height;
634}else{
635viewW = width;
636viewH = height;
637}
638
639auto ortho = glm::ortho(0.f, viewW, 0.f, viewH, nearDist, farDist);
640
641matrixMode(OF_MATRIX_PROJECTION);
642loadMatrix(ortho); // make ortho our new projection matrix.
643
644matrixMode(OF_MATRIX_MODELVIEW);
645loadViewMatrix(glm::mat4(1.0));
646
647currentEyePos = glm::vec3{viewW/2.0f, viewH/2.0f, nearDist };
648}
649
650//----------------------------------------------------------
651//Resets openGL parameters back to OF defaults
652void ofGLProgrammableRenderer::setupGraphicDefaults(){
653setStyle(ofStyle());
654path.setMode(ofPath::POLYLINES);
655path.setUseShapeColor(false);
656}
657
658//----------------------------------------------------------
659void ofGLProgrammableRenderer::setupScreen(){
660beginDefaultShader();
661setupScreenPerspective(); // assume defaults
662}
663
664//----------------------------------------------------------
665void ofGLProgrammableRenderer::setCircleResolution(int res){
666if((int)circlePolyline.size()!=res+1){
667circlePolyline.clear();
668circlePolyline.arc(0,0,0,1,1,0,360,res);
669circleMesh.getVertices() = circlePolyline.getVertices();
670path.setCircleResolution(res);
671}
672currentStyle.circleResolution = res;
673}
674
675//----------------------------------------------------------
676void ofGLProgrammableRenderer::setPolyMode(ofPolyWindingMode mode){
677currentStyle.polyMode = mode;
678path.setPolyWindingMode(mode);
679}
680
681//our openGL wrappers
682//----------------------------------------------------------
683void ofGLProgrammableRenderer::pushMatrix(){
684matrixStack.pushMatrix();
685}
686
687//----------------------------------------------------------
688void ofGLProgrammableRenderer::popMatrix(){
689matrixStack.popMatrix();
690uploadCurrentMatrix();
691}
692
693//----------------------------------------------------------
694void ofGLProgrammableRenderer::translate(const glm::vec3& p){
695translate(p.x, p.y, p.z);
696}
697
698//----------------------------------------------------------
699void ofGLProgrammableRenderer::translate(float x, float y, float z){
700matrixStack.translate(x,y,z);
701uploadCurrentMatrix();
702}
703
704//----------------------------------------------------------
705void ofGLProgrammableRenderer::scale(float xAmnt, float yAmnt, float zAmnt){
706matrixStack.scale(xAmnt, yAmnt, zAmnt);
707uploadCurrentMatrix();
708}
709
710//----------------------------------------------------------
711void ofGLProgrammableRenderer::rotateRad(float radians, float vecX, float vecY, float vecZ){
712matrixStack.rotateRad(radians, vecX, vecY, vecZ);
713uploadCurrentMatrix();
714}
715
716//----------------------------------------------------------
717void ofGLProgrammableRenderer::rotateXRad(float radians){
718rotateRad(radians, 1, 0, 0);
719}
720
721//----------------------------------------------------------
722void ofGLProgrammableRenderer::rotateYRad(float radians){
723rotateRad(radians, 0, 1, 0);
724}
725
726//----------------------------------------------------------
727void ofGLProgrammableRenderer::rotateZRad(float radians){
728rotateRad(radians, 0, 0, 1);
729}
730
731//same as ofRotateZ
732//----------------------------------------------------------
733void ofGLProgrammableRenderer::rotateRad(float radians){
734rotateZRad(radians);
735}
736
737//----------------------------------------------------------
738void ofGLProgrammableRenderer::matrixMode(ofMatrixMode mode){
739matrixStack.matrixMode(mode);
740}
741
742//----------------------------------------------------------
743void ofGLProgrammableRenderer::loadIdentityMatrix (void){
744matrixStack.loadIdentityMatrix();
745uploadCurrentMatrix();
746}
747
748//----------------------------------------------------------
749void ofGLProgrammableRenderer::loadMatrix (const glm::mat4 & m){
750matrixStack.loadMatrix(m);
751uploadCurrentMatrix();
752}
753
754//----------------------------------------------------------
755void ofGLProgrammableRenderer::loadMatrix (const float *m){
756loadMatrix(glm::make_mat4(m));
757}
758
759//----------------------------------------------------------
760void ofGLProgrammableRenderer::multMatrix (const glm::mat4 & m){
761matrixStack.multMatrix(m);
762uploadCurrentMatrix();
763}
764
765//----------------------------------------------------------
766void ofGLProgrammableRenderer::multMatrix (const float *m){
767multMatrix(glm::make_mat4(m));
768}
769
770//----------------------------------------------------------
771void ofGLProgrammableRenderer::loadViewMatrix(const glm::mat4 & m){
772matrixStack.loadViewMatrix(m);
773uploadCurrentMatrix();
774}
775
776//----------------------------------------------------------
777void ofGLProgrammableRenderer::multViewMatrix(const glm::mat4 & m){
778matrixStack.multViewMatrix(m);
779uploadCurrentMatrix();
780}
781
782//----------------------------------------------------------
783glm::mat4 ofGLProgrammableRenderer::getCurrentViewMatrix() const{
784return matrixStack.getViewMatrix();
785}
786
787//----------------------------------------------------------
788glm::mat4 ofGLProgrammableRenderer::getCurrentNormalMatrix() const{
789return glm::transpose(glm::inverse(getCurrentMatrix(OF_MATRIX_MODELVIEW)));
790}
791
792//----------------------------------------------------------
793glm::mat4 ofGLProgrammableRenderer::getCurrentModelMatrix() const{
794return matrixStack.getModelMatrix();
795}
796
797//----------------------------------------------------------
798glm::vec3 ofGLProgrammableRenderer::getCurrentEyePosition() const {
799return currentEyePos;
800}
801
802//----------------------------------------------------------
803void ofGLProgrammableRenderer::uploadCurrentMatrix(){
804if(!currentShader) return;
805// uploads the current matrix to the current shader.
806switch(matrixStack.getCurrentMatrixMode()){
807case OF_MATRIX_MODELVIEW:
808currentShader->setUniformMatrix4f(MODEL_MATRIX_UNIFORM, matrixStack.getModelMatrix());
809currentShader->setUniformMatrix4f(VIEW_MATRIX_UNIFORM, matrixStack.getViewMatrix());
810currentShader->setUniformMatrix4f(MODELVIEW_MATRIX_UNIFORM, matrixStack.getModelViewMatrix());
811currentShader->setUniformMatrix4f(MODELVIEW_PROJECTION_MATRIX_UNIFORM, matrixStack.getModelViewProjectionMatrix());
812if(currentMaterial){
813currentMaterial->uploadMatrices(*currentShader,*this);
814}
815break;
816case OF_MATRIX_PROJECTION:
817currentShader->setUniformMatrix4f(PROJECTION_MATRIX_UNIFORM, matrixStack.getProjectionMatrix());
818currentShader->setUniformMatrix4f(MODELVIEW_PROJECTION_MATRIX_UNIFORM, matrixStack.getModelViewProjectionMatrix());
819break;
820case OF_MATRIX_TEXTURE:
821currentShader->setUniformMatrix4f(TEXTURE_MATRIX_UNIFORM, matrixStack.getTextureMatrix());
822break;
823}
824
825}
826
827//----------------------------------------------------------
828glm::mat4 ofGLProgrammableRenderer::getCurrentMatrix(ofMatrixMode matrixMode_) const {
829switch (matrixMode_) {
830case OF_MATRIX_MODELVIEW:
831return matrixStack.getModelViewMatrix();
832break;
833case OF_MATRIX_PROJECTION:
834return matrixStack.getProjectionMatrix();
835break;
836case OF_MATRIX_TEXTURE:
837return matrixStack.getTextureMatrix();
838break;
839default:
840ofLogWarning() << "Invalid getCurrentMatrix query";
841return glm::mat4(1.0);
842break;
843}
844}
845
846//----------------------------------------------------------
847glm::mat4 ofGLProgrammableRenderer::getCurrentOrientationMatrix() const {
848return matrixStack.getOrientationMatrix();
849}
850//----------------------------------------------------------
851void ofGLProgrammableRenderer::setColor(const ofColor & color){
852setColor(color.r,color.g,color.b,color.a);
853}
854
855//----------------------------------------------------------
856void ofGLProgrammableRenderer::setColor(const ofColor & color, int _a){
857setColor(color.r,color.g,color.b,_a);
858}
859
860//----------------------------------------------------------
861void ofGLProgrammableRenderer::setColor(int _r, int _g, int _b){
862setColor(_r, _g, _b, 255);
863}
864
865//----------------------------------------------------------
866void ofGLProgrammableRenderer::setColor(int _r, int _g, int _b, int _a){
867ofColor newColor(_r,_g,_b,_a);
868if(newColor!=currentStyle.color){
869currentStyle.color = newColor;
870if(currentShader){
871currentShader->setUniform4f(COLOR_UNIFORM,_r/255.,_g/255.,_b/255.,_a/255.);
872}
873}
874}
875
876//----------------------------------------------------------
877void ofGLProgrammableRenderer::setColor(int gray){
878setColor(gray, gray, gray);
879}
880
881//----------------------------------------------------------
882void ofGLProgrammableRenderer::setHexColor(int hexColor){
883int r = (hexColor >> 16) & 0xff;
884int g = (hexColor >> 8) & 0xff;
885int b = (hexColor >> 0) & 0xff;
886setColor(r,g,b);
887}
888
889//----------------------------------------------------------
890void ofGLProgrammableRenderer::setBitmapTextMode(ofDrawBitmapMode mode){
891currentStyle.drawBitmapMode = mode;
892}
893
894//----------------------------------------------------------
895void ofGLProgrammableRenderer::clear(){
896glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
897}
898
899//----------------------------------------------------------
900void ofGLProgrammableRenderer::clear(float r, float g, float b, float a) {
901glClearColor(r / 255., g / 255., b / 255., a / 255.);
902glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
903}
904
905//----------------------------------------------------------
906void ofGLProgrammableRenderer::clear(float brightness, float a) {
907clear(brightness, brightness, brightness, a);
908}
909
910//----------------------------------------------------------
911void ofGLProgrammableRenderer::clearAlpha() {
912glColorMask(0, 0, 0, 1);
913glClearColor(0, 0, 0, 1);
914glClear(GL_COLOR_BUFFER_BIT);
915glColorMask(1, 1, 1, 1);
916}
917
918//----------------------------------------------------------
919void ofGLProgrammableRenderer::setBackgroundAuto(bool bAuto){
920bBackgroundAuto = bAuto;
921}
922
923//----------------------------------------------------------
924bool ofGLProgrammableRenderer::getBackgroundAuto(){
925return bBackgroundAuto;
926}
927
928//----------------------------------------------------------
929ofColor ofGLProgrammableRenderer::getBackgroundColor(){
930return currentStyle.bgColor;
931}
932
933//----------------------------------------------------------
934void ofGLProgrammableRenderer::setBackgroundColor(const ofColor & c){
935currentStyle.bgColor = c;
936glClearColor(currentStyle.bgColor[0]/255., currentStyle.bgColor[1]/255., currentStyle.bgColor[2]/255., currentStyle.bgColor[3]/255.);
937}
938
939//----------------------------------------------------------
940void ofGLProgrammableRenderer::background(const ofColor & c){
941setBackgroundColor(c);
942glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
943}
944
945//----------------------------------------------------------
946void ofGLProgrammableRenderer::background(float brightness) {
947background(ofColor(brightness));
948}
949
950//----------------------------------------------------------
951void ofGLProgrammableRenderer::background(int hexColor, float _a){
952background ( (hexColor >> 16) & 0xff, (hexColor >> 8) & 0xff, (hexColor >> 0) & 0xff, _a);
953}
954
955//----------------------------------------------------------
956void ofGLProgrammableRenderer::background(int r, int g, int b, int a){
957background(ofColor(r,g,b,a));
958}
959
960//----------------------------------------------------------
961void ofGLProgrammableRenderer::setFillMode(ofFillFlag fill){
962currentStyle.bFill = (fill==OF_FILLED);
963if(currentStyle.bFill){
964path.setFilled(true);
965path.setStrokeWidth(0);
966#ifndef TARGET_OPENGLES
967// GLES does not support glPolygonMode
968glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
969#endif
970}else{
971path.setFilled(false);
972path.setStrokeWidth(currentStyle.lineWidth);
973#ifndef TARGET_OPENGLES
974// GLES does not support glPolygonMode
975glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
976#endif
977}
978}
979
980//----------------------------------------------------------
981ofFillFlag ofGLProgrammableRenderer::getFillMode(){
982if(currentStyle.bFill){
983return OF_FILLED;
984}else{
985return OF_OUTLINE;
986}
987}
988
989//----------------------------------------------------------
990void ofGLProgrammableRenderer::setRectMode(ofRectMode mode){
991currentStyle.rectMode = mode;
992}
993
994//----------------------------------------------------------
995ofRectMode ofGLProgrammableRenderer::getRectMode(){
996return currentStyle.rectMode;
997}
998
999//----------------------------------------------------------
1000void ofGLProgrammableRenderer::setLineWidth(float lineWidth){
1001// tig: glLinewidth is 'kind of' deprecated.
1002// http://www.opengl.org/registry/doc/glspec32.core.20090803.pdf
1003// p.330: "LineWidth values greater than 1.0 will generate an
1004// INVALID_VALUE error".
1005// use geometry shaders to draw lines of varying thickness...
1006
1007currentStyle.lineWidth = lineWidth;
1008if(!currentStyle.bFill){
1009path.setStrokeWidth(lineWidth);
1010}
1011//glLineWidth(lineWidth);
1012}
1013
1014//----------------------------------------------------------
1015void ofGLProgrammableRenderer::setDepthTest(bool depthTest) {
1016if(depthTest) {
1017glEnable(GL_DEPTH_TEST);
1018} else {
1019glDisable(GL_DEPTH_TEST);
1020}
1021}
1022
1023//----------------------------------------------------------
1024void ofGLProgrammableRenderer::setLineSmoothing(bool smooth){
1025currentStyle.smoothing = smooth;
1026}
1027
1028//----------------------------------------------------------
1029void ofGLProgrammableRenderer::startSmoothing(){
1030// TODO :: needs ES2 code.
1031}
1032
1033//----------------------------------------------------------
1034void ofGLProgrammableRenderer::endSmoothing(){
1035// TODO :: needs ES2 code.
1036}
1037
1038//----------------------------------------------------------
1039void ofGLProgrammableRenderer::setBlendMode(ofBlendMode blendMode){
1040switch (blendMode){
1041case OF_BLENDMODE_DISABLED:
1042glDisable(GL_BLEND);
1043break;
1044
1045case OF_BLENDMODE_ALPHA:
1046glEnable(GL_BLEND);
1047glBlendEquation(GL_FUNC_ADD);
1048glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1049break;
1050
1051case OF_BLENDMODE_ADD:
1052glEnable(GL_BLEND);
1053glBlendEquation(GL_FUNC_ADD);
1054glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1055break;
1056
1057case OF_BLENDMODE_MULTIPLY:
1058glEnable(GL_BLEND);
1059glBlendEquation(GL_FUNC_ADD);
1060glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA /* GL_ZERO or GL_ONE_MINUS_SRC_ALPHA */);
1061break;
1062
1063case OF_BLENDMODE_SCREEN:
1064glEnable(GL_BLEND);
1065glBlendEquation(GL_FUNC_ADD);
1066glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE);
1067break;
1068
1069case OF_BLENDMODE_SUBTRACT:
1070glEnable(GL_BLEND);
1071glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
1072glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1073break;
1074
1075default:
1076break;
1077}
1078currentStyle.blendingMode = blendMode;
1079}
1080
1081//----------------------------------------------------------
1082void ofGLProgrammableRenderer::enablePointSprites(){
1083#ifdef TARGET_OPENGLES
1084#ifndef TARGET_PROGRAMMABLE_GL
1085glEnable(GL_POINT_SPRITE_OES);
1086#endif
1087#else
1088glEnable(GL_PROGRAM_POINT_SIZE);
1089#endif
1090}
1091
1092//----------------------------------------------------------
1093void ofGLProgrammableRenderer::disablePointSprites(){
1094#ifdef TARGET_OPENGLES
1095#ifndef TARGET_PROGRAMMABLE_GL
1096glEnable(GL_POINT_SPRITE_OES);
1097#endif
1098#else
1099glDisable(GL_PROGRAM_POINT_SIZE);
1100#endif
1101}
1102
1103
1104//----------------------------------------------------------
1105void ofGLProgrammableRenderer::enableAntiAliasing(){
1106#if !defined(TARGET_PROGRAMMABLE_GL) || !defined(TARGET_OPENGLES)
1107glEnable(GL_MULTISAMPLE);
1108#endif
1109}
1110
1111//----------------------------------------------------------
1112void ofGLProgrammableRenderer::disableAntiAliasing(){
1113#if !defined(TARGET_PROGRAMMABLE_GL) || !defined(TARGET_OPENGLES)
1114glDisable(GL_MULTISAMPLE);
1115#endif
1116}
1117
1118//----------------------------------------------------------
1119const ofShader & ofGLProgrammableRenderer::getCurrentShader() const{
1120return *currentShader;
1121}
1122
1123//----------------------------------------------------------
1124void ofGLProgrammableRenderer::setAlphaBitmapText(bool bitmapText){
1125bool wasBitmapStringEnabled = bitmapStringEnabled;
1126bitmapStringEnabled = bitmapText;
1127
1128if(wasBitmapStringEnabled!=bitmapText){
1129if(currentShader) currentShader->setUniform1f(BITMAP_STRING_UNIFORM,bitmapText);
1130}
1131}
1132
1133ofStyle ofGLProgrammableRenderer::getStyle() const{
1134return currentStyle;
1135}
1136
1137void ofGLProgrammableRenderer::pushStyle(){
1138styleHistory.push_back(currentStyle);
1139//if we are over the max number of styles we have set, then delete the oldest styles.
1140if( styleHistory.size() > OF_MAX_STYLE_HISTORY ){
1141styleHistory.pop_front();
1142//should we warn here?
1143ofLogWarning("ofGraphics") << "ofPushStyle(): maximum number of style pushes << " << OF_MAX_STYLE_HISTORY << " reached, did you forget to pop somewhere?";
1144}
1145}
1146
1147void ofGLProgrammableRenderer::popStyle(){
1148if( styleHistory.size() ){
1149setStyle(styleHistory.back());
1150styleHistory.pop_back();
1151}
1152}
1153
1154void ofGLProgrammableRenderer::setStyle(const ofStyle & style){
1155
1156//color
1157setColor((int)style.color.r, (int)style.color.g, (int)style.color.b, (int)style.color.a);
1158
1159//bg color
1160setBackgroundColor(style.bgColor);
1161
1162//circle resolution - don't worry it only recalculates the display list if the res has changed
1163setCircleResolution(style.circleResolution);
1164
1165setCurveResolution(style.curveResolution);
1166
1167//line width - finally!
1168setLineWidth(style.lineWidth);
1169
1170//ofSetDepthTest(style.depthTest); removed since it'll break old projects setting depth test through glEnable
1171
1172//rect mode: corner/center
1173setRectMode(style.rectMode);
1174
1175//poly mode: winding type
1176setPolyMode(style.polyMode);
1177
1178//fill
1179if(style.bFill ){
1180setFillMode(OF_FILLED);
1181}else{
1182setFillMode(OF_OUTLINE);
1183}
1184
1185//smoothing
1186/*if(style.smoothing ){
1187enableSmoothing();
1188}else{
1189disableSmoothing();
1190}*/
1191
1192//blending
1193setBlendMode(style.blendingMode);
1194
1195currentStyle = style;
1196}
1197
1198void ofGLProgrammableRenderer::setCurveResolution(int resolution){
1199currentStyle.curveResolution = resolution;
1200path.setCurveResolution(resolution);
1201}
1202
1203//----------------------------------------------------------
1204void ofGLProgrammableRenderer::setAttributes(bool vertices, bool color, bool tex, bool normals){
1205bool wasColorsEnabled = colorsEnabled;
1206bool wasUsingTexture = texCoordsEnabled & (currentTextureTarget!=OF_NO_TEXTURE);
1207
1208texCoordsEnabled = tex;
1209colorsEnabled = color;
1210normalsEnabled = normals;
1211
1212if(!uniqueShader || currentMaterial){
1213beginDefaultShader();
1214}
1215
1216bool usingTexture = tex & (currentTextureTarget!=OF_NO_TEXTURE);
1217if(wasUsingTexture!=usingTexture){
1218if(currentShader) currentShader->setUniform1f(USE_TEXTURE_UNIFORM,usingTexture);
1219}
1220if(wasColorsEnabled!=color){
1221if(currentShader) currentShader->setUniform1f(USE_COLORS_UNIFORM,color);
1222}
1223}
1224
1225//----------------------------------------------------------
1226void ofGLProgrammableRenderer::enableTextureTarget(const ofTexture & tex, int textureLocation){
1227bool wasUsingTexture = texCoordsEnabled & (currentTextureTarget!=OF_NO_TEXTURE);
1228currentTextureTarget = tex.texData.textureTarget;
1229
1230if(!uniqueShader || currentMaterial){
1231beginDefaultShader();
1232}
1233
1234bool usingTexture = texCoordsEnabled & (currentTextureTarget!=OF_NO_TEXTURE);
1235if(wasUsingTexture!=usingTexture){
1236if(currentShader) currentShader->setUniform1f(USE_TEXTURE_UNIFORM,usingTexture);
1237}
1238
1239if((currentTextureTarget!=OF_NO_TEXTURE) && currentShader){
1240currentShader->setUniformTexture("src_tex_unit"+ofToString(textureLocation),tex,textureLocation);
1241}
1242}
1243
1244//----------------------------------------------------------
1245void ofGLProgrammableRenderer::disableTextureTarget(int textureTarget, int textureLocation){
1246bool wasUsingTexture = texCoordsEnabled & (currentTextureTarget!=OF_NO_TEXTURE);
1247currentTextureTarget = OF_NO_TEXTURE;
1248
1249if(!uniqueShader || currentMaterial){
1250beginDefaultShader();
1251}
1252
1253bool usingTexture = texCoordsEnabled & (currentTextureTarget!=OF_NO_TEXTURE);
1254if(wasUsingTexture!=usingTexture){
1255if(currentShader) currentShader->setUniform1f(USE_TEXTURE_UNIFORM,usingTexture);
1256}
1257glActiveTexture(GL_TEXTURE0+textureLocation);
1258glBindTexture(textureTarget, 0);
1259glActiveTexture(GL_TEXTURE0);
1260}
1261
1262//----------------------------------------------------------
1263GLenum ofGLProgrammableRenderer::getCurrentTextureTarget(){
1264return currentTextureTarget;
1265}
1266
1267//----------------------------------------------------------
1268void ofGLProgrammableRenderer::setAlphaMaskTex(const ofTexture & tex){
1269alphaMaskTextureTarget = tex.getTextureData().textureTarget;
1270if(alphaMaskTextureTarget==GL_TEXTURE_2D){
1271alphaMask2DShader.begin();
1272}else{
1273alphaMaskRectShader.begin();
1274}
1275enableTextureTarget(tex, 1);
1276}
1277
1278//----------------------------------------------------------
1279void ofGLProgrammableRenderer::disableAlphaMask(){
1280disableTextureTarget(alphaMaskTextureTarget,1);
1281if(alphaMaskTextureTarget==GL_TEXTURE_2D){
1282alphaMask2DShader.end();
1283}else{
1284alphaMaskRectShader.end();
1285}
1286}
1287
1288//----------------------------------------------------------
1289void ofGLProgrammableRenderer::bind(const ofShader & shader){
1290if(currentShader && *currentShader==shader){
1291return;
1292}
1293
1294if(bIsShadowDepthPass) {
1295// if we are not the shadow shader, lets unbind it
1296if(!settingDefaultShader && currentShadow && currentShader ) {
1297// lets assume it's bound?
1298if(!bCustomShadowShader) {
1299glUseProgram(0);
1300}
1301// we are assuming that since it's a custom depth shader, it all will be taken care of ...
1302bCustomShadowShader=true;
1303}
1304}
1305
1306glUseProgram(shader.getProgram());
1307
1308currentShader = &shader;
1309uploadMatrices();
1310setDefaultUniforms();
1311if(!settingDefaultShader){
1312usingCustomShader = true;
1313}
1314}
1315
1316//----------------------------------------------------------
1317void ofGLProgrammableRenderer::unbind(const ofShader & shader){
1318glUseProgram(0);
1319usingCustomShader = false;
1320bCustomShadowShader=false;
1321beginDefaultShader();
1322}
1323
1324//----------------------------------------------------------
1325void ofGLProgrammableRenderer::begin(const ofFbo & fbo, ofFboMode mode){
1326pushView();
1327pushStyle();
1328if(mode & OF_FBOMODE_MATRIXFLIP){
1329matrixStack.setRenderSurface(fbo);
1330}else{
1331matrixStack.setRenderSurfaceNoMatrixFlip(fbo);
1332}
1333viewport();
1334if(mode & OF_FBOMODE_PERSPECTIVE){
1335setupScreenPerspective();
1336}else{
1337uploadMatrices();
1338}
1339bind(fbo);
1340}
1341
1342//----------------------------------------------------------
1343void ofGLProgrammableRenderer::end(const ofFbo & fbo){
1344unbind(fbo);
1345matrixStack.setRenderSurface(*window);
1346uploadMatrices();
1347popStyle();
1348popView();
1349}
1350
1351//----------------------------------------------------------
1352void ofGLProgrammableRenderer::bind(const ofFbo & fbo){
1353if (currentFramebufferId == fbo.getId()){
1354ofLogWarning() << "Framebuffer with id: " << fbo.getId() << " cannot be bound onto itself. \n" <<
1355"Most probably you forgot to end() the current framebuffer before calling begin() again or you forgot to allocate() before calling begin().";
1356return;
1357}
1358// this method could just as well have been placed in ofBaseGLRenderer
1359// and shared over both programmable and fixed function renderer.
1360// I'm keeping it here, so that if we want to do more fancyful
1361// named framebuffers with GL 4.5+, we can have
1362// different implementations.
1363framebufferIdStack.push_back(currentFramebufferId);
1364currentFramebufferId = fbo.getId();
1365glBindFramebuffer(GL_FRAMEBUFFER, currentFramebufferId);
1366}
1367
1368#ifndef TARGET_OPENGLES
1369//----------------------------------------------------------
1370void ofGLProgrammableRenderer::bindForBlitting(const ofFbo & fboSrc, ofFbo & fboDst, int attachmentPoint){
1371if (currentFramebufferId == fboSrc.getId()){
1372ofLogWarning() << "Framebuffer with id: " << fboSrc.getId() << " cannot be bound onto itself. \n" <<
1373"Most probably you forgot to end() the current framebuffer before calling getTexture().";
1374return;
1375}
1376// this method could just as well have been placed in ofBaseGLRenderer
1377// and shared over both programmable and fixed function renderer.
1378// I'm keeping it here, so that if we want to do more fancyful
1379// named framebuffers with GL 4.5+, we can have
1380// different implementations.
1381framebufferIdStack.push_back(currentFramebufferId);
1382currentFramebufferId = fboSrc.getId();
1383glBindFramebuffer(GL_READ_FRAMEBUFFER, currentFramebufferId);
1384glReadBuffer(GL_COLOR_ATTACHMENT0 + attachmentPoint);
1385glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboDst.getIdDrawBuffer());
1386glDrawBuffer(GL_COLOR_ATTACHMENT0 + attachmentPoint);
1387}
1388#endif
1389
1390//----------------------------------------------------------
1391void ofGLProgrammableRenderer::unbind(const ofFbo & fbo){
1392if(framebufferIdStack.empty()){
1393ofLogError() << "unbalanced fbo bind/unbind binding default framebuffer";
1394currentFramebufferId = defaultFramebufferId;
1395}else{
1396currentFramebufferId = framebufferIdStack.back();
1397framebufferIdStack.pop_back();
1398}
1399glBindFramebuffer(GL_FRAMEBUFFER, currentFramebufferId);
1400fbo.flagDirty();
1401}
1402
1403//----------------------------------------------------------
1404void ofGLProgrammableRenderer::bind(const ofBaseMaterial & material){
1405if( bIsShadowDepthPass ) {
1406// currentMaterial = nullptr;
1407// we are the shadow depth pass right now, we don't need
1408// textures or lighting, etc.
1409return;
1410}
1411currentMaterial = &material;
1412// FIXME: this invalidates the previous shader to avoid that
1413// when binding 2 materials one after another, the second won't
1414// get the right parameters.
1415currentMaterial->bind(*this);
1416currentShader = nullptr;
1417beginDefaultShader();
1418}
1419
1420//----------------------------------------------------------
1421void ofGLProgrammableRenderer::bind(const ofShadow & shadow) {
1422currentShadow = &shadow;
1423bIsShadowDepthPass = true;
1424beginDefaultShader();
1425}
1426
1427//----------------------------------------------------------
1428void ofGLProgrammableRenderer::bind(const ofShadow & shadow, GLenum aCubeFace) {
1429shadowCubeFace = aCubeFace;
1430bind( shadow );
1431}
1432
1433//----------------------------------------------------------
1434void ofGLProgrammableRenderer::unbind(const ofBaseMaterial &){
1435if(currentMaterial) {
1436currentMaterial->unbind(*this);
1437}
1438currentMaterial = nullptr;
1439if( bIsShadowDepthPass ) {
1440// we are the shadow depth pass right now, we don't need
1441// textures or lighting, etc.
1442return;
1443}
1444beginDefaultShader();
1445}
1446
1447//----------------------------------------------------------
1448void ofGLProgrammableRenderer::unbind(const ofShadow & shadow) {
1449currentShadow = nullptr;
1450bIsShadowDepthPass = false;
1451bCustomShadowShader = false;
1452beginDefaultShader();
1453}
1454
1455//----------------------------------------------------------
1456void ofGLProgrammableRenderer::unbind(const ofShadow & shadow, GLenum aCubeFace) {
1457unbind(shadow);
1458}
1459
1460//----------------------------------------------------------
1461void ofGLProgrammableRenderer::enableLighting(){
1462
1463}
1464
1465//----------------------------------------------------------
1466void ofGLProgrammableRenderer::disableLighting(){
1467}
1468
1469//----------------------------------------------------------
1470void ofGLProgrammableRenderer::enableLight(int){
1471
1472}
1473
1474//----------------------------------------------------------
1475void ofGLProgrammableRenderer::disableLight(int){
1476
1477}
1478
1479//----------------------------------------------------------
1480bool ofGLProgrammableRenderer::getLightingEnabled(){
1481return true;
1482}
1483
1484//----------------------------------------------------------
1485void ofGLProgrammableRenderer::bind(const ofTexture & texture, int location){
1486//we could check if it has been allocated - but we don't do that in draw()
1487if(texture.getAlphaMask()){
1488setAlphaMaskTex(*texture.getAlphaMask());
1489}
1490enableTextureTarget(texture,location);
1491
1492
1493if(ofGetUsingNormalizedTexCoords()) {
1494matrixMode(OF_MATRIX_TEXTURE);
1495pushMatrix();
1496glm::mat4 m = glm::mat4(1.0);
1497
1498#ifndef TARGET_OPENGLES
1499if(texture.texData.textureTarget == GL_TEXTURE_RECTANGLE_ARB)
1500m = glm::scale(m, glm::vec3(texture.texData.width, texture.texData.height, 1.0f));
1501else
1502#endif
1503m = glm::scale(m, glm::vec3(texture.texData.width / texture.texData.tex_w, texture.texData.height / texture.texData.tex_h, 1.0f));
1504
1505loadMatrix(m);
1506matrixMode(OF_MATRIX_MODELVIEW);
1507}
1508if(texture.isUsingTextureMatrix()){
1509matrixMode(OF_MATRIX_TEXTURE);
1510if(!ofGetUsingNormalizedTexCoords()) pushMatrix();
1511multMatrix(texture.getTextureMatrix());
1512matrixMode(OF_MATRIX_MODELVIEW);
1513}
1514}
1515
1516//----------------------------------------------------------
1517void ofGLProgrammableRenderer::unbind(const ofTexture & texture, int location){
1518disableTextureTarget(texture.texData.textureTarget,location);
1519if(texture.getAlphaMask()){
1520disableAlphaMask();
1521}
1522
1523if(texture.isUsingTextureMatrix() || ofGetUsingNormalizedTexCoords()) {
1524matrixMode(OF_MATRIX_TEXTURE);
1525popMatrix();
1526matrixMode(OF_MATRIX_MODELVIEW);
1527}
1528}
1529
1530//----------------------------------------------------------
1531void ofGLProgrammableRenderer::bind(const ofCamera & camera, const ofRectangle & _viewport){
1532pushView();
1533viewport(_viewport);
1534setOrientation(matrixStack.getOrientation(),camera.isVFlipped());
1535matrixMode(OF_MATRIX_PROJECTION);
1536loadMatrix(camera.getProjectionMatrix(_viewport));
1537matrixMode(OF_MATRIX_MODELVIEW);
1538loadViewMatrix(camera.getModelViewMatrix());
1539currentEyePos = camera.getPosition();
1540}
1541
1542//----------------------------------------------------------
1543void ofGLProgrammableRenderer::unbind(const ofCamera & camera){
1544popView();
1545}
1546
1547
1548//----------------------------------------------------------
1549void ofGLProgrammableRenderer::uploadMatrices(){
1550if(!currentShader) return;
1551currentShader->setUniformMatrix4f(MODEL_MATRIX_UNIFORM, matrixStack.getModelMatrix());
1552currentShader->setUniformMatrix4f(VIEW_MATRIX_UNIFORM, matrixStack.getViewMatrix());
1553currentShader->setUniformMatrix4f(MODELVIEW_MATRIX_UNIFORM, matrixStack.getModelViewMatrix());
1554currentShader->setUniformMatrix4f(PROJECTION_MATRIX_UNIFORM, matrixStack.getProjectionMatrix());
1555currentShader->setUniformMatrix4f(TEXTURE_MATRIX_UNIFORM, matrixStack.getTextureMatrix());
1556currentShader->setUniformMatrix4f(MODELVIEW_PROJECTION_MATRIX_UNIFORM, matrixStack.getModelViewProjectionMatrix());
1557if(currentMaterial){
1558currentMaterial->uploadMatrices(*currentShader,*this);
1559}
1560}
1561
1562//----------------------------------------------------------
1563void ofGLProgrammableRenderer::setDefaultUniforms(){
1564if(!currentShader) return;
1565currentShader->setUniform4f(COLOR_UNIFORM, currentStyle.color.r/255.,currentStyle.color.g/255.,currentStyle.color.b/255.,currentStyle.color.a/255.);
1566bool usingTexture = texCoordsEnabled & (currentTextureTarget!=OF_NO_TEXTURE);
1567currentShader->setUniform1f(USE_TEXTURE_UNIFORM,usingTexture);
1568currentShader->setUniform1f(USE_COLORS_UNIFORM,colorsEnabled);
1569if(currentMaterial){
1570currentMaterial->updateMaterial(*currentShader,*this);
1571currentMaterial->updateLights(*currentShader,*this);
1572currentMaterial->updateShadows(*currentShader,*this);
1573currentMaterial->updateEnvironmentMaps(*currentShader, *this);
1574}
1575if(currentShadow) {
1576if( currentShadow->isMultiCubeFacePass() ) {
1577currentShadow->updateDepth(*currentShader, shadowCubeFace, *this);
1578} else {
1579currentShadow->updateDepth(*currentShader, *this);
1580}
1581}
1582}
1583
1584//----------------------------------------------------------
1585void ofGLProgrammableRenderer::beginDefaultShader(){
1586if(usingCustomShader && !currentMaterial && !currentShadow) return;
1587if( currentShadow && bCustomShadowShader ) return;
1588
1589const ofShader * nextShader = nullptr;
1590
1591if(!uniqueShader || currentMaterial || currentShadow ){
1592if(currentShadow) {
1593nextShader = ¤tShadow->getDepthShader(*this);
1594} else if(currentMaterial){
1595// std::cout << "ofGLProgrammableRenderer::beginDefaultShader: " << currentTextureTarget << " | " << ofGetFrameNum() << std::endl;
1596nextShader = ¤tMaterial->getShader(currentTextureTarget,colorsEnabled,*this);
1597
1598}else if(bitmapStringEnabled){
1599nextShader = &bitmapStringShader;
1600
1601}else if(colorsEnabled && texCoordsEnabled){
1602switch(currentTextureTarget){
1603#ifndef TARGET_OPENGLES
1604case GL_TEXTURE_RECTANGLE_ARB:
1605nextShader = &defaultTexRectColor;
1606break;
1607#endif
1608case GL_TEXTURE_2D:
1609nextShader = &defaultTex2DColor;
1610break;
1611case OF_NO_TEXTURE:
1612nextShader = &defaultNoTexColor;
1613break;
1614#ifdef TARGET_ANDROID
1615case GL_TEXTURE_EXTERNAL_OES:
1616nextShader = &defaultOESTexColor;
1617break;
1618#endif
1619}
1620
1621}else if(colorsEnabled){
1622nextShader = &defaultNoTexColor;
1623
1624}else if(texCoordsEnabled){
1625switch(currentTextureTarget){
1626#ifndef TARGET_OPENGLES
1627case GL_TEXTURE_RECTANGLE_ARB:
1628nextShader = &defaultTexRectNoColor;
1629break;
1630#endif
1631case GL_TEXTURE_2D:
1632nextShader = &defaultTex2DNoColor;
1633break;
1634case OF_NO_TEXTURE:
1635nextShader = &defaultNoTexNoColor;
1636break;
1637#ifdef TARGET_ANDROID
1638case GL_TEXTURE_EXTERNAL_OES:
1639nextShader = &defaultOESTexNoColor;
1640break;
1641#endif
1642}
1643
1644}else{
1645nextShader = &defaultNoTexNoColor;
1646}
1647
1648}else{
1649nextShader = &defaultUniqueShader;
1650}
1651
1652if(nextShader){
1653if(!currentShader || *currentShader!=*nextShader){
1654settingDefaultShader = true;
1655bind(*nextShader);
1656settingDefaultShader = false;
1657}
1658}
1659}
1660
1661//----------------------------------------------------------
1662void ofGLProgrammableRenderer::drawLine(float x1, float y1, float z1, float x2, float y2, float z2) const{
1663ofGLProgrammableRenderer * mutThis = const_cast<ofGLProgrammableRenderer*>(this);
1664lineMesh.getVertices()[0] = {x1,y1,z1};
1665lineMesh.getVertices()[1] = {x2,y2,z2};
1666
1667// use smoothness, if requested:
1668if (currentStyle.smoothing) mutThis->startSmoothing();
1669
1670draw(lineMesh,OF_MESH_FILL,false,false,false);
1671
1672// use smoothness, if requested:
1673if (currentStyle.smoothing) mutThis->endSmoothing();
1674}
1675
1676//----------------------------------------------------------
1677void ofGLProgrammableRenderer::drawRectangle(float x, float y, float z, float w, float h) const{
1678ofGLProgrammableRenderer * mutThis = const_cast<ofGLProgrammableRenderer*>(this);
1679if (currentStyle.rectMode == OF_RECTMODE_CORNER){
1680rectMesh.getVertices()[0] = {x,y,z};
1681rectMesh.getVertices()[1] = {x+w, y, z};
1682rectMesh.getVertices()[2] = {x+w, y+h, z};
1683rectMesh.getVertices()[3] = {x, y+h, z};
1684}else{
1685rectMesh.getVertices()[0] = {x-w/2.0f, y-h/2.0f, z};
1686rectMesh.getVertices()[1] = {x+w/2.0f, y-h/2.0f, z};
1687rectMesh.getVertices()[2] = {x+w/2.0f, y+h/2.0f, z};
1688rectMesh.getVertices()[3] = {x-w/2.0f, y+h/2.0f, z};
1689}
1690
1691// use smoothness, if requested:
1692if (currentStyle.smoothing && !currentStyle.bFill) mutThis->startSmoothing();
1693
1694rectMesh.setMode(currentStyle.bFill ? OF_PRIMITIVE_TRIANGLE_FAN : OF_PRIMITIVE_LINE_LOOP);
1695draw(rectMesh,OF_MESH_FILL,false,false,false);
1696
1697// use smoothness, if requested:
1698if (currentStyle.smoothing && !currentStyle.bFill) mutThis->endSmoothing();
1699}
1700
1701//----------------------------------------------------------
1702void ofGLProgrammableRenderer::drawTriangle(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3) const{
1703ofGLProgrammableRenderer * mutThis = const_cast<ofGLProgrammableRenderer*>(this);
1704triangleMesh.getVertices()[0] = {x1,y1,z1};
1705triangleMesh.getVertices()[1] = {x2,y2,z2};
1706triangleMesh.getVertices()[2] = {x3,y3,z3};
1707
1708// use smoothness, if requested:
1709if (currentStyle.smoothing && !currentStyle.bFill) mutThis->startSmoothing();
1710
1711triangleMesh.setMode(currentStyle.bFill ? OF_PRIMITIVE_TRIANGLE_STRIP : OF_PRIMITIVE_LINE_LOOP);
1712draw(triangleMesh,OF_MESH_FILL,false,false,false);
1713
1714// use smoothness, if requested:
1715if (currentStyle.smoothing && !currentStyle.bFill) mutThis->endSmoothing();
1716}
1717
1718//----------------------------------------------------------
1719void ofGLProgrammableRenderer::drawCircle(float x, float y, float z, float radius) const{
1720ofGLProgrammableRenderer * mutThis = const_cast<ofGLProgrammableRenderer*>(this);
1721const auto & circleCache = circlePolyline.getVertices();
1722for(int i=0;i<(int)circleCache.size();i++){
1723circleMesh.getVertices()[i] = {radius*circleCache[i].x+x,radius*circleCache[i].y+y,z};
1724}
1725
1726// use smoothness, if requested:
1727if (currentStyle.smoothing && !currentStyle.bFill) mutThis->startSmoothing();
1728
1729circleMesh.setMode(currentStyle.bFill ? OF_PRIMITIVE_TRIANGLE_FAN : OF_PRIMITIVE_LINE_STRIP);
1730draw(circleMesh,OF_MESH_FILL,false,false,false);
1731
1732// use smoothness, if requested:
1733if (currentStyle.smoothing && !currentStyle.bFill) mutThis->endSmoothing();
1734}
1735
1736//----------------------------------------------------------
1737void ofGLProgrammableRenderer::drawEllipse(float x, float y, float z, float width, float height) const{
1738ofGLProgrammableRenderer * mutThis = const_cast<ofGLProgrammableRenderer*>(this);
1739float radiusX = width*0.5;
1740float radiusY = height*0.5;
1741const auto & circleCache = circlePolyline.getVertices();
1742for(int i=0;i<(int)circleCache.size();i++){
1743circleMesh.getVertices()[i] = {radiusX*circlePolyline[i].x+x,radiusY*circlePolyline[i].y+y,z};
1744}
1745
1746// use smoothness, if requested:
1747if (currentStyle.smoothing && !currentStyle.bFill) mutThis->startSmoothing();
1748
1749circleMesh.setMode(currentStyle.bFill ? OF_PRIMITIVE_TRIANGLE_FAN : OF_PRIMITIVE_LINE_STRIP);
1750draw(circleMesh,OF_MESH_FILL,false,false,false);
1751
1752// use smoothness, if requested:
1753if (currentStyle.smoothing && !currentStyle.bFill) mutThis->endSmoothing();
1754}
1755
1756//----------------------------------------------------------
1757void ofGLProgrammableRenderer::drawString(string textString, float x, float y, float z) const{
1758ofGLProgrammableRenderer * mutThis = const_cast<ofGLProgrammableRenderer*>(this);
1759float sx = 0;
1760float sy = 0;
1761
1762///////////////////////////
1763// APPLY TRANSFORM / VIEW
1764///////////////////////////
1765//
1766
1767bool hasModelView = false;
1768bool hasProjection = false;
1769bool hasViewport = false;
1770
1771ofRectangle rViewport;
1772glm::mat4 modelView = glm::mat4(1.0);
1773
1774switch (currentStyle.drawBitmapMode) {
1775
1776case OF_BITMAPMODE_SIMPLE:
1777
1778sx += x;
1779sy += y;
1780break;
1781
1782case OF_BITMAPMODE_SCREEN:
1783
1784hasViewport = true;
1785mutThis->pushView();
1786
1787rViewport = matrixStack.getFullSurfaceViewport();
1788mutThis->viewport(rViewport);
1789
1790mutThis->matrixMode(OF_MATRIX_PROJECTION);
1791mutThis->loadIdentityMatrix();
1792mutThis->matrixMode(OF_MATRIX_MODELVIEW);
1793
1794modelView = glm::translate(modelView, glm::vec3(-1,-1,0));
1795modelView = glm::scale(modelView, glm::vec3(2/rViewport.width, 2/rViewport.height, 1));
1796modelView = glm::translate(modelView, glm::vec3(x,y, 0));
1797mutThis->loadMatrix(modelView);
1798break;
1799
1800case OF_BITMAPMODE_VIEWPORT:
1801
1802rViewport = getCurrentViewport();
1803
1804hasProjection = true;
1805mutThis->matrixMode(OF_MATRIX_PROJECTION);
1806mutThis->pushMatrix();
1807mutThis->loadIdentityMatrix();
1808
1809hasModelView = true;
1810mutThis->matrixMode(OF_MATRIX_MODELVIEW);
1811mutThis->pushMatrix();
1812
1813modelView = glm::translate(modelView, glm::vec3(-1,-1,0));
1814modelView = glm::scale(modelView, glm::vec3(2/rViewport.width, 2/rViewport.height, 1));
1815modelView = glm::translate(modelView, glm::vec3(x,y, 0));
1816mutThis->loadMatrix(modelView);
1817break;
1818
1819case OF_BITMAPMODE_MODEL:
1820
1821hasModelView = true;
1822mutThis->matrixMode(OF_MATRIX_MODELVIEW);
1823mutThis->pushMatrix();
1824
1825mutThis->translate(x, y, z);
1826break;
1827
1828case OF_BITMAPMODE_MODEL_BILLBOARD:
1829{
1830//our aim here is to draw to screen
1831//at the viewport position related
1832//to the world position x,y,z
1833
1834// tig: we want to get the signed normalised screen coordinates (-1,+1) of our point (x,y,z)
1835// that's projection * modelview * point in GLSL multiplication order
1836// then doing the good old (v + 1.0) / 2. to get unsigned normalized screen (0,1) coordinates.
1837// we then multiply x by width and y by height to get window coordinates.
1838
1839rViewport = getCurrentViewport();
1840
1841glm::mat4 mat = matrixStack.getProjectionMatrixNoOrientation() * matrixStack.getModelViewMatrix();
1842glm::vec4 dScreen4 = mat * glm::vec4(x,y,z,1.0);
1843glm::vec3 dScreen = glm::vec3(dScreen4) / dScreen4.w;
1844dScreen += glm::vec3(1.0) ;
1845dScreen *= 0.5;
1846
1847dScreen.x += rViewport.x;
1848dScreen.x *= rViewport.width;
1849
1850dScreen.y += rViewport.y;
1851dScreen.y *= rViewport.height;
1852
1853if (dScreen.z >= 1) return;
1854
1855
1856hasProjection = true;
1857mutThis->matrixMode(OF_MATRIX_PROJECTION);
1858mutThis->pushMatrix();
1859mutThis->loadIdentityMatrix();
1860
1861hasModelView = true;
1862mutThis->matrixMode(OF_MATRIX_MODELVIEW);
1863mutThis->pushMatrix();
1864
1865modelView = glm::translate(modelView, glm::vec3(-1,-1,0));
1866modelView = glm::scale(modelView, glm::vec3(2/rViewport.width, 2/rViewport.height, 1));
1867modelView = glm::translate(modelView, glm::vec3(dScreen.x, dScreen.y, 0));
1868mutThis->loadMatrix(modelView);
1869}
1870break;
1871
1872default:
1873break;
1874}
1875//
1876///////////////////////////
1877
1878// tig: we switch over to our built-in bitmapstring shader
1879// to render text. This gives us more flexibility & control
1880// and does not mess/interfere with client side shaders.
1881
1882// (c) enable texture once before we start drawing each char (no point turning it on and off constantly)
1883//We do this because its way faster
1884mutThis->setAlphaBitmapText(true);
1885ofMesh charMesh = bitmapFont.getMesh(textString, sx, sy, currentStyle.drawBitmapMode, isVFlipped());
1886mutThis->bind(bitmapFont.getTexture(),0);
1887draw(charMesh,OF_MESH_FILL,false,true,false);
1888mutThis->unbind(bitmapFont.getTexture(),0);
1889mutThis->setAlphaBitmapText(false);
1890
1891
1892if (hasViewport){
1893mutThis->popView();
1894}else{
1895if (hasModelView){
1896mutThis->popMatrix();
1897}
1898
1899if (hasProjection)
1900{
1901mutThis->matrixMode(OF_MATRIX_PROJECTION);
1902mutThis->popMatrix();
1903mutThis->matrixMode(OF_MATRIX_MODELVIEW);
1904}
1905}
1906}
1907
1908
1909//----------------------------------------------------------
1910void ofGLProgrammableRenderer::drawString(const ofTrueTypeFont & font, string text, float x, float y) const{
1911ofGLProgrammableRenderer * mutThis = const_cast<ofGLProgrammableRenderer*>(this);
1912ofBlendMode blendMode = currentStyle.blendingMode;
1913
1914mutThis->setBlendMode(OF_BLENDMODE_ALPHA);
1915
1916mutThis->bind(font.getFontTexture(),0);
1917draw(font.getStringMesh(text,x,y,isVFlipped()),OF_MESH_FILL);
1918mutThis->unbind(font.getFontTexture(),0);
1919
1920mutThis->setBlendMode(blendMode);
1921}
1922
1923#define STRINGIFY(x) #x
1924
1925
1926// ----------------------------------------------------------------------
1927// tig: GLSL #150 shaders written against spec:
1928// http://www.opengl.org/registry/doc/GLSLangSpec.1.50.09.pdf
1929
1930#ifdef TARGET_OPENGLES
1931static const string vertex_shader_header =
1932"%extensions%\n"
1933"precision highp float;\n"
1934"#define IN attribute\n"
1935"#define OUT varying\n"
1936"#define TEXTURE texture2D\n"
1937"#define TARGET_OPENGLES\n";
1938static const string fragment_shader_header =
1939"%extensions%\n"
1940"precision highp float;\n"
1941"#define IN varying\n"
1942"#define OUT\n"
1943"#define TEXTURE texture2D\n"
1944"#define FRAG_COLOR gl_FragColor\n"
1945"#define TARGET_OPENGLES\n";
1946#else
1947static const string vertex_shader_header =
1948"#version %glsl_version%\n"
1949"%extensions%\n"
1950"#define IN in\n"
1951"#define OUT out\n"
1952"#define TEXTURE texture\n";
1953static const string fragment_shader_header =
1954"#version %glsl_version%\n"
1955"%extensions%\n"
1956"#define IN in\n"
1957"#define OUT out\n"
1958"#define TEXTURE texture\n"
1959"#define FRAG_COLOR fragColor\n"
1960"out vec4 fragColor;\n";
1961#endif
1962
1963static const string defaultVertexShader = vertex_shader_header + STRINGIFY(
1964uniform mat4 projectionMatrix;
1965uniform mat4 modelViewMatrix;
1966uniform mat4 textureMatrix;
1967uniform mat4 modelViewProjectionMatrix;
1968
1969IN vec4 position;
1970IN vec2 texcoord;
1971IN vec4 color;
1972IN vec3 normal;
1973
1974OUT vec4 colorVarying;
1975OUT vec2 texCoordVarying;
1976OUT vec4 normalVarying;
1977
1978void main()
1979{
1980colorVarying = color;
1981texCoordVarying = (textureMatrix*vec4(texcoord.x,texcoord.y,0,1)).xy;
1982gl_Position = modelViewProjectionMatrix * position;
1983}
1984);
1985
1986// ----------------------------------------------------------------------
1987
1988static const string defaultFragmentShaderTexRectColor = fragment_shader_header + STRINGIFY(
1989
1990uniform sampler2DRect src_tex_unit0;
1991uniform float usingTexture;
1992uniform float usingColors;
1993uniform vec4 globalColor;
1994
1995IN float depth;
1996IN vec4 colorVarying;
1997IN vec2 texCoordVarying;
1998
1999
2000void main(){
2001FRAG_COLOR = TEXTURE(src_tex_unit0, texCoordVarying) * colorVarying;
2002}
2003);
2004
2005// ----------------------------------------------------------------------
2006
2007static const string defaultFragmentShaderTexRectNoColor = fragment_shader_header + STRINGIFY(
2008
2009uniform sampler2DRect src_tex_unit0;
2010uniform float usingTexture;
2011uniform float usingColors;
2012uniform vec4 globalColor;
2013
2014IN float depth;
2015IN vec4 colorVarying;
2016IN vec2 texCoordVarying;
2017
2018void main(){
2019FRAG_COLOR = TEXTURE(src_tex_unit0, texCoordVarying)* globalColor;
2020}
2021);
2022
2023// ----------------------------------------------------------------------
2024
2025static const string alphaMaskFragmentShaderTexRectNoColor = fragment_shader_header + STRINGIFY(
2026
2027uniform sampler2DRect src_tex_unit0;
2028uniform sampler2DRect src_tex_unit1;
2029uniform float usingTexture;
2030uniform float usingColors;
2031uniform vec4 globalColor;
2032
2033IN float depth;
2034IN vec4 colorVarying;
2035IN vec2 texCoordVarying;
2036
2037void main(){
2038FRAG_COLOR = vec4(TEXTURE(src_tex_unit0, texCoordVarying).rgb, TEXTURE(src_tex_unit1, texCoordVarying).r)* globalColor;
2039}
2040);
2041
2042// ----------------------------------------------------------------------
2043
2044static const string alphaMaskFragmentShaderTex2DNoColor = fragment_shader_header + STRINGIFY(
2045
2046uniform sampler2D src_tex_unit0;
2047uniform sampler2D src_tex_unit1;
2048uniform float usingTexture;
2049uniform float usingColors;
2050uniform vec4 globalColor;
2051
2052IN float depth;
2053IN vec4 colorVarying;
2054IN vec2 texCoordVarying;
2055
2056void main(){
2057FRAG_COLOR = vec4(TEXTURE(src_tex_unit0, texCoordVarying).rgb, TEXTURE(src_tex_unit1, texCoordVarying).r)* globalColor;
2058}
2059);
2060
2061// ----------------------------------------------------------------------
2062
2063static const string defaultFragmentShaderTex2DColor = fragment_shader_header + STRINGIFY(
2064
2065uniform sampler2D src_tex_unit0;
2066uniform float usingTexture;
2067uniform float usingColors;
2068uniform vec4 globalColor;
2069
2070IN float depth;
2071IN vec4 colorVarying;
2072IN vec2 texCoordVarying;
2073
2074void main(){
2075FRAG_COLOR = TEXTURE(src_tex_unit0, texCoordVarying) * colorVarying;
2076}
2077);
2078
2079// ----------------------------------------------------------------------
2080
2081static const string defaultFragmentShaderTex2DNoColor = fragment_shader_header + STRINGIFY(
2082
2083uniform sampler2D src_tex_unit0;
2084uniform float usingTexture;
2085uniform float usingColors;
2086uniform vec4 globalColor;
2087
2088IN float depth;
2089IN vec4 colorVarying;
2090IN vec2 texCoordVarying;
2091void main(){
2092FRAG_COLOR = TEXTURE(src_tex_unit0, texCoordVarying) * globalColor;
2093}
2094);
2095
2096// ----------------------------------------------------------------------
2097
2098static const string defaultFragmentShaderOESTexNoColor = fragment_shader_header + STRINGIFY(
2099
2100uniform samplerExternalOES src_tex_unit0;
2101uniform float usingTexture;
2102uniform float usingColors;
2103uniform vec4 globalColor;
2104
2105IN float depth;
2106IN vec4 colorVarying;
2107IN vec2 texCoordVarying;
2108
2109void main(){
2110FRAG_COLOR = TEXTURE(src_tex_unit0, texCoordVarying) * globalColor;
2111}
2112);
2113
2114// ----------------------------------------------------------------------
2115
2116static const string defaultFragmentShaderOESTexColor = fragment_shader_header + STRINGIFY(
2117
2118uniform samplerExternalOES src_tex_unit0;
2119uniform float usingTexture;
2120uniform float usingColors;
2121uniform vec4 globalColor;
2122
2123IN float depth;
2124IN vec4 colorVarying;
2125IN vec2 texCoordVarying;
2126
2127void main(){
2128FRAG_COLOR = TEXTURE(src_tex_unit0, texCoordVarying) * colorVarying;
2129}
2130);
2131
2132// ----------------------------------------------------------------------
2133
2134static const string defaultFragmentShaderNoTexColor = fragment_shader_header + STRINGIFY (
2135
2136uniform float usingTexture;
2137uniform float usingColors;
2138uniform vec4 globalColor;
2139
2140IN float depth;
2141IN vec4 colorVarying;
2142IN vec2 texCoordVarying;
2143
2144void main(){
2145FRAG_COLOR = colorVarying;
2146}
2147);
2148
2149// ----------------------------------------------------------------------
2150
2151static const string defaultFragmentShaderNoTexNoColor = fragment_shader_header + STRINGIFY(
2152
2153uniform float usingTexture;
2154uniform float usingColors;
2155uniform vec4 globalColor;
2156
2157IN float depth;
2158IN vec4 colorVarying;
2159IN vec2 texCoordVarying;
2160
2161void main(){
2162FRAG_COLOR = globalColor;
2163}
2164);
2165
2166// ----------------------------------------------------------------------
2167
2168static const string bitmapStringVertexShader = vertex_shader_header + STRINGIFY(
2169
2170uniform mat4 projectionMatrix;
2171uniform mat4 modelViewMatrix;
2172uniform mat4 textureMatrix;
2173uniform mat4 modelViewProjectionMatrix;
2174
2175IN vec4 position;
2176IN vec4 color;
2177IN vec2 texcoord;
2178
2179OUT vec2 texCoordVarying;
2180
2181void main()
2182{
2183texCoordVarying = texcoord;
2184gl_Position = modelViewProjectionMatrix * position;
2185}
2186);
2187
2188// ----------------------------------------------------------------------
2189
2190static const string bitmapStringFragmentShader = fragment_shader_header + STRINGIFY(
2191
2192uniform sampler2D src_tex_unit0;
2193uniform vec4 globalColor;
2194
2195IN vec2 texCoordVarying;
2196
2197void main()
2198{
2199
2200vec4 tex = TEXTURE(src_tex_unit0, texCoordVarying);
2201// We will not write anything to the framebuffer if we have a transparent pixel
2202// This makes sure we don't mess up our depth buffer.
2203if (tex.a < 0.5) discard;
2204FRAG_COLOR = globalColor * tex;
2205}
2206);
2207
2208// ----------------------------------------------------------------------
2209// changing shaders in raspberry pi is very expensive so we use only one shader there
2210// in desktop openGL these are not used but we declare it to avoid more ifdefs
2211
2212static const string uniqueVertexShader = vertex_shader_header + STRINGIFY(
2213
2214uniform mat4 modelViewMatrix;
2215uniform mat4 projectionMatrix;
2216uniform mat4 textureMatrix;
2217uniform mat4 modelViewProjectionMatrix;
2218uniform float usingTexture;
2219uniform float usingColors;
2220uniform vec4 globalColor;
2221
2222IN vec4 position;
2223IN vec4 color;
2224IN vec4 normal;
2225IN vec2 texcoord;
2226
2227OUT vec4 colorVarying;
2228OUT vec2 texCoordVarying;
2229
2230void main(){
2231gl_Position = modelViewProjectionMatrix * position;
2232if(usingTexture>.5) texCoordVarying = (textureMatrix*vec4(texcoord.x,texcoord.y,0,1)).xy;
2233if(usingColors>.5) colorVarying = color;
2234else colorVarying = globalColor;
2235}
2236);
2237
2238// ----------------------------------------------------------------------
2239static const string uniqueFragmentShader = fragment_shader_header + STRINGIFY(
2240
2241uniform sampler2D src_tex_unit0;
2242uniform float usingTexture;
2243uniform float bitmapText;
2244
2245IN vec4 colorVarying;
2246IN vec2 texCoordVarying;
2247
2248void main(){
2249vec4 tex;
2250if(usingTexture>.5){
2251tex = TEXTURE(src_tex_unit0, texCoordVarying);
2252if(bitmapText>.5 && tex.a < 0.5){
2253discard;
2254}else{
2255FRAG_COLOR = colorVarying*tex;
2256}
2257}else{
2258FRAG_COLOR = colorVarying;
2259}
2260}
2261);
2262
2263// ----------------------------------------------------------------------
2264// video color space conversion shaders
2265static const string FRAGMENT_SHADER_YUY2 = STRINGIFY(
2266uniform SAMPLER src_tex_unit0;\n
2267uniform vec4 globalColor;\n
2268
2269IN vec4 colorVarying;\n
2270IN vec2 texCoordVarying;\n
2271uniform float onePixel;\n
2272uniform float textureWidth;\n
2273
2274const vec3 offset = vec3(-0.0625, -0.5, -0.5);\n
2275const vec3 rcoeff = vec3(1.164, 0.000, 1.596);\n
2276const vec3 gcoeff = vec3(1.164,-0.391,-0.813);\n
2277const vec3 bcoeff = vec3(1.164, 2.018, 0.000);\n
2278
2279
2280void main(){\n
2281vec3 yuv;\n
2282yuv.x=TEXTURE(src_tex_unit0,texCoordVarying).r;\n
2283float x = texCoordVarying.x * textureWidth;\n
2284if(mod(x,2.0)>0.5){\n
2285yuv.y=TEXTURE(src_tex_unit0,vec2(texCoordVarying.x-onePixel,texCoordVarying.y)).%g;\n
2286yuv.z=TEXTURE(src_tex_unit0,texCoordVarying).%g;\n
2287}else{\n
2288yuv.y=TEXTURE(src_tex_unit0,texCoordVarying).%g;\n
2289yuv.z=TEXTURE(src_tex_unit0,vec2(texCoordVarying.x+onePixel,texCoordVarying.y)).%g;\n
2290}\n
2291yuv += offset;\n
2292float r = dot(yuv, rcoeff);\n
2293float g = dot(yuv, gcoeff);\n
2294float b = dot(yuv, bcoeff);\n
2295FRAG_COLOR=vec4(r,g,b,1.0) * globalColor;\n
2296}\n
2297);
2298
2299// ----------------------------------------------------------------------
2300static const string FRAGMENT_SHADER_NV12_NV21 = STRINGIFY(
2301uniform SAMPLER Ytex;\n
2302uniform SAMPLER UVtex;\n
2303uniform vec4 globalColor;\n
2304uniform vec2 tex_scaleUV;\n
2305
2306IN vec4 colorVarying;\n
2307IN vec2 texCoordVarying;\n
2308
2309const vec3 offset = vec3(-0.0625, -0.5, -0.5);\n
2310const vec3 rcoeff = vec3(1.164, 0.000, 1.596);\n
2311const vec3 gcoeff = vec3(1.164,-0.391,-0.813);\n
2312const vec3 bcoeff = vec3(1.164, 2.018, 0.000);\n
2313
2314
2315void main(){\n
2316vec3 yuv;\n
2317yuv.x=TEXTURE(Ytex,texCoordVarying).r;\n
2318yuv.yz=TEXTURE(UVtex,texCoordVarying * tex_scaleUV).%r%g;\n
2319yuv += offset;\n
2320float r = dot(yuv, rcoeff);\n
2321float g = dot(yuv, gcoeff);\n
2322float b = dot(yuv, bcoeff);\n
2323FRAG_COLOR=vec4(r,g,b,1.0) * globalColor;\n
2324}\n
2325);
2326
2327// ----------------------------------------------------------------------
2328static const string FRAGMENT_SHADER_PLANAR_YUV = STRINGIFY(
2329uniform SAMPLER Ytex;\n
2330uniform SAMPLER Utex;\n
2331uniform SAMPLER Vtex;\n
2332uniform vec2 tex_scaleY;\n
2333uniform vec2 tex_scaleU;\n
2334uniform vec2 tex_scaleV;\n
2335uniform vec4 globalColor;\n
2336
2337IN vec4 colorVarying;\n
2338IN vec2 texCoordVarying;\n
2339
2340const vec3 offset = vec3(-0.0625, -0.5, -0.5);\n
2341const vec3 rcoeff = vec3(1.164, 0.000, 1.596);\n
2342const vec3 gcoeff = vec3(1.164,-0.391,-0.813);\n
2343const vec3 bcoeff = vec3(1.164, 2.018, 0.000);\n
2344
2345
2346void main(){\n
2347vec3 yuv;\n
2348yuv.x=TEXTURE(Ytex,texCoordVarying * tex_scaleY).r;\n
2349yuv.y=TEXTURE(Utex,texCoordVarying * tex_scaleU).r;\n
2350yuv.z=TEXTURE(Vtex,texCoordVarying * tex_scaleV).r;\n
2351yuv += offset;\n
2352float r = dot(yuv, rcoeff);\n
2353float g = dot(yuv, gcoeff);\n
2354float b = dot(yuv, bcoeff);\n
2355FRAG_COLOR=vec4(r,g,b,1.0) * globalColor;\n
2356}\n
2357);
2358
2359static string defaultShaderHeader(string header, GLenum textureTarget, int major, int minor){
2360ofStringReplace(header,"%glsl_version%",ofGLSLVersionFromGL(major,minor));
2361#ifndef TARGET_OPENGLES
2362if(major<4 && minor<2){
2363ofStringReplace(header,"%extensions%","#extension GL_ARB_texture_rectangle : enable");
2364}else{
2365ofStringReplace(header,"%extensions%","");
2366}
2367#else
2368ofStringReplace(header,"%extensions%","#extension GL_OES_standard_derivatives : enable");
2369#endif
2370if(textureTarget==GL_TEXTURE_2D){
2371header += "#define SAMPLER sampler2D\n";
2372}else{
2373header += "#define SAMPLER sampler2DRect\n";
2374}
2375return header;
2376}
2377
2378
2379static string shaderSource(const string & src, int major, int minor){
2380string shaderSrc = src;
2381ofStringReplace(shaderSrc,"%glsl_version%",ofGLSLVersionFromGL(major,minor));
2382#ifndef TARGET_OPENGLES
2383if(major<4 && minor<2){
2384ofStringReplace(shaderSrc,"%extensions%","#extension GL_ARB_texture_rectangle : enable");
2385}else{
2386ofStringReplace(shaderSrc,"%extensions%","");
2387}
2388#else
2389ofStringReplace(shaderSrc,"%extensions%","");
2390#endif
2391return shaderSrc;
2392}
2393
2394#ifdef TARGET_ANDROID
2395static string shaderOESSource(const string & src, int major, int minor){
2396string shaderSrc = src;
2397ofStringReplace(shaderSrc,"%glsl_version%",ofGLSLVersionFromGL(major,minor));
2398ofStringReplace(shaderSrc,"%extensions%","#extension GL_OES_EGL_image_external : require");
2399return shaderSrc;
2400}
2401#endif
2402
2403static string videoFragmentShaderSource(const ofBaseVideoDraws & video, int major, int minor){
2404string src;
2405switch(video.getPixelFormat()){
2406case OF_PIXELS_YUY2:
2407src = FRAGMENT_SHADER_YUY2;
2408#ifndef TARGET_OPENGLES
2409ofStringReplace(src,"%g","g");
2410#else
2411ofStringReplace(src,"%g","a");
2412#endif
2413break;
2414case OF_PIXELS_NV12:
2415src = FRAGMENT_SHADER_NV12_NV21;
2416#ifndef TARGET_OPENGLES
2417ofStringReplace(src,"%r%g","rg");
2418#else
2419ofStringReplace(src,"%r%g","ra");
2420#endif
2421break;
2422case OF_PIXELS_NV21:
2423src = FRAGMENT_SHADER_NV12_NV21;
2424#ifndef TARGET_OPENGLES
2425ofStringReplace(src,"%r%g","gr");
2426#else
2427ofStringReplace(src,"%r%g","ar");
2428#endif
2429break;
2430case OF_PIXELS_YV12:
2431case OF_PIXELS_I420:
2432src = FRAGMENT_SHADER_PLANAR_YUV;
2433break;
2434case OF_PIXELS_RGB:
2435case OF_PIXELS_BGR:
2436case OF_PIXELS_RGB565:
2437case OF_PIXELS_RGBA:
2438case OF_PIXELS_BGRA:
2439case OF_PIXELS_GRAY:
2440default:
2441break;
2442}
2443
2444string header = fragment_shader_header;
2445GLenum textureTarget = video.getTexture().getTextureData().textureTarget;
2446if(textureTarget==GL_TEXTURE_2D){
2447header += "#define SAMPLER sampler2D\n";
2448}
2449#ifndef TARGET_OPENGLES
2450else if(textureTarget==GL_TEXTURE_RECTANGLE){
2451header += "#define SAMPLER sampler2DRect\n";
2452}
2453#endif
2454return shaderSource(header + src, major, minor);
2455}
2456
2457string ofGLProgrammableRenderer::defaultVertexShaderHeader(GLenum textureTarget){
2458return defaultShaderHeader(vertex_shader_header,textureTarget,major,minor);
2459}
2460
2461string ofGLProgrammableRenderer::defaultFragmentShaderHeader(GLenum textureTarget){
2462return defaultShaderHeader(fragment_shader_header,textureTarget,major,minor);
2463}
2464
2465void ofGLProgrammableRenderer::setup(int _major, int _minor){
2466glGetError();
2467#ifdef TARGET_OPENGLES
2468// OpenGL ES might have set a default frame buffer for
2469// MSAA rendering to the window, bypassing ofFbo, so we
2470// can't trust ofFbo to have correctly tracked the bind
2471// state. Therefore, we are forced to use the slower glGet() method
2472// to be sure to get the correct default framebuffer.
2473GLint currentFrameBuffer;
2474glGetIntegerv(GL_FRAMEBUFFER_BINDING, ¤tFrameBuffer);
2475defaultFramebufferId = currentFrameBuffer;
2476currentFramebufferId = defaultFramebufferId;
2477#endif
2478
2479major = _major;
2480minor = _minor;
2481#ifdef TARGET_RASPBERRY_PI
2482uniqueShader = true;
2483#else
2484uniqueShader = false;
2485#endif
2486
2487if(uniqueShader){
2488defaultUniqueShader.setupShaderFromSource(GL_VERTEX_SHADER,shaderSource(uniqueVertexShader, major, minor));
2489defaultUniqueShader.setupShaderFromSource(GL_FRAGMENT_SHADER,shaderSource(uniqueFragmentShader, major, minor));
2490defaultUniqueShader.bindDefaults();
2491defaultUniqueShader.linkProgram();
2492beginDefaultShader();
2493}else{
2494#ifndef TARGET_OPENGLES
2495defaultTexRectColor.setupShaderFromSource(GL_VERTEX_SHADER,shaderSource(defaultVertexShader,major, minor));
2496defaultTexRectNoColor.setupShaderFromSource(GL_VERTEX_SHADER,shaderSource(defaultVertexShader,major, minor));
2497alphaMaskRectShader.setupShaderFromSource(GL_VERTEX_SHADER,shaderSource(defaultVertexShader,major, minor));
2498#endif
2499defaultTex2DColor.setupShaderFromSource(GL_VERTEX_SHADER,shaderSource(defaultVertexShader,major, minor));
2500defaultNoTexColor.setupShaderFromSource(GL_VERTEX_SHADER,shaderSource(defaultVertexShader,major, minor));
2501defaultTex2DNoColor.setupShaderFromSource(GL_VERTEX_SHADER,shaderSource(defaultVertexShader,major, minor));
2502defaultNoTexNoColor.setupShaderFromSource(GL_VERTEX_SHADER,shaderSource(defaultVertexShader,major, minor));
2503alphaMask2DShader.setupShaderFromSource(GL_VERTEX_SHADER,shaderSource(defaultVertexShader,major, minor));
2504
2505#ifndef TARGET_OPENGLES
2506defaultTexRectColor.setupShaderFromSource(GL_FRAGMENT_SHADER,shaderSource(defaultFragmentShaderTexRectColor,major, minor));
2507defaultTexRectNoColor.setupShaderFromSource(GL_FRAGMENT_SHADER,shaderSource(defaultFragmentShaderTexRectNoColor,major, minor));
2508alphaMaskRectShader.setupShaderFromSource(GL_FRAGMENT_SHADER,shaderSource(alphaMaskFragmentShaderTexRectNoColor,major, minor));
2509#endif
2510defaultTex2DColor.setupShaderFromSource(GL_FRAGMENT_SHADER,shaderSource(defaultFragmentShaderTex2DColor,major, minor));
2511defaultNoTexColor.setupShaderFromSource(GL_FRAGMENT_SHADER,shaderSource(defaultFragmentShaderNoTexColor,major, minor));
2512defaultTex2DNoColor.setupShaderFromSource(GL_FRAGMENT_SHADER,shaderSource(defaultFragmentShaderTex2DNoColor,major, minor));
2513defaultNoTexNoColor.setupShaderFromSource(GL_FRAGMENT_SHADER,shaderSource(defaultFragmentShaderNoTexNoColor,major, minor));
2514alphaMask2DShader.setupShaderFromSource(GL_FRAGMENT_SHADER,shaderSource(alphaMaskFragmentShaderTex2DNoColor,major, minor));
2515
2516
2517bitmapStringShader.setupShaderFromSource(GL_VERTEX_SHADER, shaderSource(bitmapStringVertexShader,major, minor));
2518bitmapStringShader.setupShaderFromSource(GL_FRAGMENT_SHADER, shaderSource(bitmapStringFragmentShader,major, minor));
2519
2520#ifndef TARGET_OPENGLES
2521defaultTexRectColor.bindDefaults();
2522defaultTexRectNoColor.bindDefaults();
2523alphaMaskRectShader.bindDefaults();
2524#endif
2525defaultTex2DColor.bindDefaults();
2526defaultNoTexColor.bindDefaults();
2527defaultTex2DNoColor.bindDefaults();
2528defaultNoTexNoColor.bindDefaults();
2529alphaMask2DShader.bindDefaults();
2530
2531#ifndef TARGET_OPENGLES
2532defaultTexRectColor.linkProgram();
2533defaultTexRectNoColor.linkProgram();
2534alphaMaskRectShader.linkProgram();
2535#endif
2536defaultTex2DColor.linkProgram();
2537defaultNoTexColor.linkProgram();
2538defaultTex2DNoColor.linkProgram();
2539defaultNoTexNoColor.linkProgram();
2540alphaMask2DShader.linkProgram();
2541
2542bitmapStringShader.bindDefaults();
2543bitmapStringShader.linkProgram();
2544
2545
2546#ifdef TARGET_ANDROID
2547defaultOESTexNoColor.setupShaderFromSource(GL_VERTEX_SHADER,shaderOESSource(defaultVertexShader,major, minor));
2548defaultOESTexColor.setupShaderFromSource(GL_VERTEX_SHADER,shaderOESSource(defaultVertexShader,major, minor));
2549defaultOESTexColor.setupShaderFromSource(GL_FRAGMENT_SHADER,shaderOESSource(defaultFragmentShaderOESTexColor,major, minor));
2550defaultOESTexNoColor.setupShaderFromSource(GL_FRAGMENT_SHADER,shaderOESSource(defaultFragmentShaderOESTexNoColor,major, minor));
2551
2552defaultOESTexColor.bindDefaults();
2553defaultOESTexNoColor.bindDefaults();
2554
2555defaultOESTexColor.linkProgram();
2556defaultOESTexNoColor.linkProgram();
2557#endif
2558}
2559
2560setupGraphicDefaults();
2561viewport();
2562setupScreenPerspective();
2563}
2564
2565const ofShader * ofGLProgrammableRenderer::getVideoShader(const ofBaseVideoDraws & video) const{
2566const ofShader * shader = nullptr;
2567GLenum target = video.getTexture().getTextureData().textureTarget;
2568switch(video.getPixelFormat()){
2569case OF_PIXELS_YUY2:
2570if(target==GL_TEXTURE_2D){
2571shader = &shaderPlanarYUY2;
2572}else{
2573shader = &shaderPlanarYUY2Rect;
2574}
2575break;
2576case OF_PIXELS_NV12:
2577if(target==GL_TEXTURE_2D){
2578shader = &shaderNV12;
2579}else{
2580shader = &shaderNV12Rect;
2581}
2582break;
2583case OF_PIXELS_NV21:
2584if(target==GL_TEXTURE_2D){
2585shader = &shaderNV21;
2586}else{
2587shader = &shaderNV21Rect;
2588}
2589break;
2590case OF_PIXELS_YV12:
2591case OF_PIXELS_I420:
2592if(target==GL_TEXTURE_2D){
2593shader = &shaderPlanarYUV;
2594}else{
2595shader = &shaderPlanarYUVRect;
2596}
2597break;
2598case OF_PIXELS_RGB:
2599case OF_PIXELS_BGR:
2600case OF_PIXELS_RGB565:
2601case OF_PIXELS_RGBA:
2602case OF_PIXELS_BGRA:
2603case OF_PIXELS_GRAY:
2604default:
2605break;
2606}
2607if(shader && !shader->isLoaded()){
2608ofShader * mutShader = const_cast<ofShader*>(shader);
2609mutShader->setupShaderFromSource(GL_VERTEX_SHADER,shaderSource(defaultVertexShader,major,minor));
2610mutShader->setupShaderFromSource(GL_FRAGMENT_SHADER,videoFragmentShaderSource(video,major,minor));
2611mutShader->bindDefaults();
2612mutShader->linkProgram();
2613}
2614return shader;
2615}
2616
2617#ifndef TARGET_OPENGLES
2618static float getTextureScaleX(const ofBaseVideoDraws & video, int plane){
2619if(!video.getTexturePlanes().empty()){
2620return video.getTexturePlanes()[plane].getWidth()/video.getWidth();
2621}else{
2622return 1.0;
2623}
2624}
2625
2626static float getTextureScaleY(const ofBaseVideoDraws & video, int plane){
2627if(!video.getTexturePlanes().empty()){
2628return video.getTexturePlanes()[plane].getHeight()/video.getHeight();
2629}else{
2630return 1.0;
2631}
2632}
2633#endif
2634
2635void ofGLProgrammableRenderer::setVideoShaderUniforms(const ofBaseVideoDraws & video, const ofShader & shader) const{
2636switch(video.getPixelFormat()){
2637case OF_PIXELS_YUY2:
2638#ifndef TARGET_OPENGLES
2639if(video.getTexture().getTextureData().textureTarget==GL_TEXTURE_RECTANGLE){
2640shader.setUniform1f("onePixel",1.0);
2641shader.setUniform1f("textureWidth",1.0);
2642}else{
2643#endif
2644shader.setUniform1f("onePixel",1.0/video.getWidth());
2645shader.setUniform1f("textureWidth",video.getWidth());
2646#ifndef TARGET_OPENGLES
2647}
2648#endif
2649shader.setUniformTexture("src_tex_unit0",video.getTexturePlanes()[0],0);
2650break;
2651case OF_PIXELS_NV12:
2652case OF_PIXELS_NV21:
2653shader.setUniformTexture("Ytex",video.getTexturePlanes()[0],0);
2654shader.setUniformTexture("UVtex",video.getTexturePlanes()[1],1);
2655#ifndef TARGET_OPENGLES
2656if(video.getTexture().getTextureData().textureTarget==GL_TEXTURE_RECTANGLE){
2657shader.setUniform2f("tex_scaleUV",getTextureScaleX(video,1),getTextureScaleY(video,1));
2658}else{
2659#endif
2660shader.setUniform2f("tex_scaleUV",1.0,1.0);
2661#ifndef TARGET_OPENGLES
2662}
2663#endif
2664break;
2665case OF_PIXELS_YV12:
2666shader.setUniformTexture("Ytex",video.getTexturePlanes()[0],0);
2667shader.setUniformTexture("Utex",video.getTexturePlanes()[2],1);
2668shader.setUniformTexture("Vtex",video.getTexturePlanes()[1],2);
2669#ifndef TARGET_OPENGLES
2670if(video.getTexture().getTextureData().textureTarget==GL_TEXTURE_RECTANGLE){
2671shader.setUniform2f("tex_scaleY",getTextureScaleX(video,0),getTextureScaleY(video,0));
2672shader.setUniform2f("tex_scaleU",getTextureScaleX(video,2),getTextureScaleY(video,2));
2673shader.setUniform2f("tex_scaleV",getTextureScaleX(video,1),getTextureScaleY(video,1));
2674}else{
2675#endif
2676shader.setUniform2f("tex_scaleY",1.0,1.0);
2677shader.setUniform2f("tex_scaleU",1.0,1.0);
2678shader.setUniform2f("tex_scaleV",1.0,1.0);
2679#ifndef TARGET_OPENGLES
2680}
2681#endif
2682break;
2683case OF_PIXELS_I420:
2684shader.setUniformTexture("Ytex",video.getTexturePlanes()[0],0);
2685shader.setUniformTexture("Utex",video.getTexturePlanes()[1],1);
2686shader.setUniformTexture("Vtex",video.getTexturePlanes()[2],2);
2687#ifndef TARGET_OPENGLES
2688if(video.getTexture().getTextureData().textureTarget==GL_TEXTURE_RECTANGLE){
2689shader.setUniform2f("tex_scaleY",getTextureScaleX(video,0),getTextureScaleY(video,0));
2690shader.setUniform2f("tex_scaleU",getTextureScaleX(video,1),getTextureScaleY(video,1));
2691shader.setUniform2f("tex_scaleV",getTextureScaleX(video,2),getTextureScaleY(video,2));
2692}else{
2693#endif
2694shader.setUniform2f("tex_scaleY",1.0,1.0);
2695shader.setUniform2f("tex_scaleU",1.0,1.0);
2696shader.setUniform2f("tex_scaleV",1.0,1.0);
2697#ifndef TARGET_OPENGLES
2698}
2699#endif
2700break;
2701default:
2702break;
2703}
2704}
2705
2706int ofGLProgrammableRenderer::getGLVersionMajor(){
2707return major;
2708}
2709
2710int ofGLProgrammableRenderer::getGLVersionMinor(){
2711return minor;
2712}
2713
2714
2715void ofGLProgrammableRenderer::saveFullViewport(ofPixels & pixels){
2716ofRectangle v = getCurrentViewport();
2717saveScreen(v.x,v.y,v.width,v.height,pixels);
2718}
2719
2720void ofGLProgrammableRenderer::saveScreen(int x, int y, int w, int h, ofPixels & pixels){
2721int sh = getViewportHeight();
2722
2723
2724#ifndef TARGET_OPENGLES
2725if(isVFlipped()){
2726y = sh - y;
2727y -= h; // top, bottom issues
2728}
2729auto pixelFormat = OF_PIXELS_BGRA;
2730pixels.allocate(w, h, pixelFormat);
2731auto glFormat = ofGetGLFormat(pixels);
2732
2733
2734ofBufferObject buffer;
2735buffer.allocate(pixels.size(), GL_STATIC_READ);
2736
2737buffer.bind(GL_PIXEL_PACK_BUFFER);
2738glReadPixels(x, y, w, h, glFormat, GL_UNSIGNED_BYTE, 0); // read the memory....
2739buffer.unbind(GL_PIXEL_PACK_BUFFER);
2740
2741if(unsigned char * p = buffer.map<unsigned char>(GL_READ_ONLY)){
2742ofPixels src;
2743src.setFromExternalPixels(p,w,h,pixelFormat);
2744src.mirrorTo(pixels,true,false);
2745buffer.unmap();
2746}else{
2747ofLogError("ofGLProgrammableRenderer") << "Error saving screen";
2748}
2749
2750#else
2751
2752int sw = getViewportWidth();
2753int numPixels = w*h;
2754if( numPixels == 0 ){
2755ofLogError("ofImage") << "grabScreen(): unable to grab screen, image width and/or height are 0: " << w << "x" << h;
2756return;
2757}
2758pixels.allocate(w, h, OF_PIXELS_RGBA);
2759
2760switch(matrixStack.getOrientation()){
2761case OF_ORIENTATION_UNKNOWN:
2762case OF_ORIENTATION_DEFAULT:
2763
2764if(isVFlipped()){
2765y = sh - y; // screen is flipped vertically.
2766y -= h;
2767}
2768
2769glPixelStorei(GL_PACK_ALIGNMENT, 1);
2770glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels.getData());
2771pixels.mirror(true,false);
2772break;
2773case OF_ORIENTATION_180:
2774
2775if(isVFlipped()){
2776x = sw - x; // screen is flipped horizontally.
2777x -= w;
2778}
2779
2780glPixelStorei(GL_PACK_ALIGNMENT, 1);
2781glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels.getData());
2782pixels.mirror(false,true);
2783break;
2784case OF_ORIENTATION_90_RIGHT:
2785swap(w,h);
2786swap(x,y);
2787if(!isVFlipped()){
2788x = sw - x; // screen is flipped horizontally.
2789x -= w;
2790
2791y = sh - y; // screen is flipped vertically.
2792y -= h;
2793}
2794
2795glPixelStorei(GL_PACK_ALIGNMENT, 1);
2796glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels.getData());
2797pixels.mirror(true,true);
2798break;
2799case OF_ORIENTATION_90_LEFT:
2800swap(w, h);
2801swap(x, y);
2802if(isVFlipped()){
2803x = sw - x; // screen is flipped horizontally.
2804x -= w;
2805
2806y = sh - y; // screen is flipped vertically.
2807y -= h;
2808}
2809
2810glPixelStorei(GL_PACK_ALIGNMENT, 1);
2811glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels.getData());
2812pixels.mirror(true,true);
2813break;
2814}
2815
2816#endif
2817}
2818
2819const of3dGraphics & ofGLProgrammableRenderer::get3dGraphics() const{
2820return graphics3d;
2821}
2822
2823of3dGraphics & ofGLProgrammableRenderer::get3dGraphics(){
2824return graphics3d;
2825}
2826
2827