void ofMaterial::initShaders(ofGLProgrammableRenderer & renderer) const{ if(!shadersInitialized || ofLightsData().size()!=shaderLights){ #ifndef TARGET_OPENGLES string vertexRectHeader = renderer.defaultVertexShaderHeader(GL_TEXTURE_RECTANGLE); string fragmentRectHeader = renderer.defaultFragmentShaderHeader(GL_TEXTURE_RECTANGLE); #endif string vertex2DHeader = renderer.defaultVertexShaderHeader(GL_TEXTURE_2D); string fragment2DHeader = renderer.defaultFragmentShaderHeader(GL_TEXTURE_2D); shaderLights = ofLightsData().size(); shaderNoTexture.setupShaderFromSource(GL_VERTEX_SHADER,vertexSource(vertex2DHeader,shaderLights,false)); shaderNoTexture.setupShaderFromSource(GL_FRAGMENT_SHADER,fragmentSource(fragment2DHeader,shaderLights,false)); shaderNoTexture.bindDefaults(); shaderNoTexture.linkProgram(); shaderTexture2D.setupShaderFromSource(GL_VERTEX_SHADER,vertexSource(vertex2DHeader,shaderLights,true)); shaderTexture2D.setupShaderFromSource(GL_FRAGMENT_SHADER,fragmentSource(fragment2DHeader,shaderLights,true)); shaderTexture2D.bindDefaults(); shaderTexture2D.linkProgram(); #ifndef TARGET_OPENGLES shaderTextureRect.setupShaderFromSource(GL_VERTEX_SHADER,vertexSource(vertexRectHeader,shaderLights,true)); shaderTextureRect.setupShaderFromSource(GL_FRAGMENT_SHADER,fragmentSource(fragmentRectHeader,shaderLights,true)); shaderTextureRect.bindDefaults(); shaderTextureRect.linkProgram(); #endif shadersInitialized = true; } }
void ofMaterial::updateLights(const ofShader & shader,ofGLProgrammableRenderer & renderer) const{ for(size_t i=0;i<ofLightsData().size();i++){ string idx = ofToString(i); shared_ptr<ofLight::Data> light = ofLightsData()[i].lock(); if(!light || !light->isEnabled){ shader.setUniform1f("lights["+idx+"].enabled",0); continue; } auto lightEyePosition = renderer.getCurrentViewMatrix() * light->position; shader.setUniform1f("lights["+idx+"].enabled",1); shader.setUniform1f("lights["+idx+"].type", light->lightType); shader.setUniform4f("lights["+idx+"].position", lightEyePosition); shader.setUniform4f("lights["+idx+"].ambient", light->ambientColor); shader.setUniform4f("lights["+idx+"].specular", light->specularColor); shader.setUniform4f("lights["+idx+"].diffuse", light->diffuseColor); if(light->lightType!=OF_LIGHT_DIRECTIONAL){ shader.setUniform1f("lights["+idx+"].constantAttenuation", light->attenuation_constant); shader.setUniform1f("lights["+idx+"].linearAttenuation", light->attenuation_linear); shader.setUniform1f("lights["+idx+"].quadraticAttenuation", light->attenuation_quadratic); } if(light->lightType==OF_LIGHT_SPOT){ auto direction = toGlm(light->position).xyz() + light->direction; auto direction4 = renderer.getCurrentViewMatrix() * glm::vec4(direction,1.0); direction = direction4.xyz() / direction4.w; direction = direction - lightEyePosition.xyz(); shader.setUniform3f("lights["+idx+"].spotDirection", glm::normalize(direction)); shader.setUniform1f("lights["+idx+"].spotExponent", light->exponent); shader.setUniform1f("lights["+idx+"].spotCutoff", light->spotCutOff); shader.setUniform1f("lights["+idx+"].spotCosCutoff", cos(ofDegToRad(light->spotCutOff))); }else if(light->lightType==OF_LIGHT_DIRECTIONAL){ auto halfVector = glm::normalize(glm::vec4(0.f, 0.f, 1.f, 0.f) + lightEyePosition); shader.setUniform3f("lights["+idx+"].halfVector", halfVector.xyz()); }else if(light->lightType==OF_LIGHT_AREA){ shader.setUniform1f("lights["+idx+"].width", light->width); shader.setUniform1f("lights["+idx+"].height", light->height); auto direction = light->position.xyz() + light->direction; auto direction4 = renderer.getCurrentViewMatrix() * glm::vec4(direction, 1.0); direction = direction4.xyz() / direction4.w; direction = direction - lightEyePosition.xyz(); shader.setUniform3f("lights["+idx+"].spotDirection", glm::normalize(direction)); auto right = toGlm(light->position).xyz() + light->right; auto right4 = renderer.getCurrentViewMatrix() * glm::vec4(right, 1.0); right = right4.xyz() / right4.w; right = right - lightEyePosition.xyz(); auto up = glm::cross(toGlm(right), direction); shader.setUniform3f("lights["+idx+"].right", glm::normalize(toGlm(right))); shader.setUniform3f("lights["+idx+"].up", glm::normalize(up)); } } }
//---------------------------------------------------------- void ofGLRenderer::loadViewMatrix(const ofMatrix4x4 & m){ int matrixMode; glGetIntegerv(GL_MATRIX_MODE,&matrixMode); matrixStack.loadViewMatrix(m); glMatrixMode(GL_MODELVIEW); glLoadMatrixf(m.getPtr()); glMatrixMode(matrixMode); if(lightingEnabled){ for(size_t i=0;i<ofLightsData().size();i++){ shared_ptr<ofLight::Data> lightData = ofLightsData()[i].lock(); if(lightData && lightData->isEnabled){ glLightfv(GL_LIGHT0 + lightData->glIndex, GL_POSITION, &lightData->position.x); } } } }
//---------------------------------------- void ofLight::setup() { if(data->glIndex==-1){ bool bLightFound = false; // search for the first free block for(size_t i=0; i<ofLightsData().size(); i++) { if(ofLightsData()[i].expired()) { data->glIndex = i; data->isEnabled = true; ofLightsData()[i] = data; bLightFound = true; break; } } if(!bLightFound && ofIsGLProgrammableRenderer()){ ofLightsData().push_back(data); data->glIndex = ofLightsData().size() - 1; data->isEnabled = true; bLightFound = true; } if( bLightFound ){ // run this the first time, since it was not found before // onPositionChanged(); setAmbientColor( getAmbientColor() ); setDiffuseColor( getDiffuseColor() ); setSpecularColor( getSpecularColor() ); setAttenuation( getAttenuationConstant(), getAttenuationLinear(), getAttenuationQuadratic() ); if(getIsSpotlight()) { setSpotlightCutOff(getSpotlightCutOff()); setSpotConcentration(getSpotConcentration()); } if(getIsSpotlight() || getIsDirectional()) { onOrientationChanged(); } }else{ ofLogError("ofLight") << "setup(): couldn't get active GL light, maximum number of "<< ofLightsData().size() << " reached"; } } }
void ofMaterial::initShaders(){ if(!shadersInitialized || ofLightsData().size()!=shaderLights){ shaderLights = ofLightsData().size(); shaderNoTexture.setupShaderFromSource(GL_VERTEX_SHADER,vertexSource(shaderLights,false,false)); shaderNoTexture.setupShaderFromSource(GL_FRAGMENT_SHADER,fragmentSource(shaderLights,false,false)); shaderNoTexture.bindDefaults(); shaderNoTexture.linkProgram(); shaderTexture2D.setupShaderFromSource(GL_VERTEX_SHADER,vertexSource(shaderLights,true,false)); shaderTexture2D.setupShaderFromSource(GL_FRAGMENT_SHADER,fragmentSource(shaderLights,true,false)); shaderTexture2D.bindDefaults(); shaderTexture2D.linkProgram(); #ifndef TARGET_OPENGLES shaderTextureRect.setupShaderFromSource(GL_VERTEX_SHADER,vertexSource(shaderLights,true,true)); shaderTextureRect.setupShaderFromSource(GL_FRAGMENT_SHADER,fragmentSource(shaderLights,true,true)); shaderTextureRect.bindDefaults(); shaderTextureRect.linkProgram(); #endif shadersInitialized = true; } }
void ofMaterial::beginShader(int texType){ initShaders(); switch(texType){ case OF_NO_TEXTURE: currentShader = &shaderNoTexture; break; case GL_TEXTURE_2D: currentShader = &shaderTexture2D; break; default: currentShader = &shaderTextureRect; break; } const ofMatrix4x4 & normalMatrix = ofGetCurrentNormalMatrix(); currentShader->begin(); currentShader->setUniformMatrix4f("normalMatrix",normalMatrix); currentShader->setUniform4fv("mat_ambient", &data.ambient.r); currentShader->setUniform4fv("mat_diffuse", &data.diffuse.r); currentShader->setUniform4fv("mat_specular", &data.specular.r); currentShader->setUniform4fv("mat_emissive", &data.emissive.r); currentShader->setUniform4fv("global_ambient", &ofGetGlobalAmbientColor().r); currentShader->setUniform1f("mat_shininess",data.shininess); for(size_t i=0;i<ofLightsData().size();i++){ string idx = ofToString(i); if(ofLightsData()[i].expired() || !ofLightsData()[i].lock()->isEnabled){ currentShader->setUniform1f("lights["+idx+"].enabled",0); continue; } shared_ptr<ofLight::Data> light = ofLightsData()[i].lock(); ofVec4f lightEyePosition = light->position * ofGetCurrentViewMatrix(); currentShader->setUniform1f("lights["+idx+"].enabled",1); currentShader->setUniform1f("lights["+idx+"].type", light->lightType); currentShader->setUniform4fv("lights["+idx+"].position", &lightEyePosition.x); currentShader->setUniform4fv("lights["+idx+"].ambient", &light->ambientColor.r); currentShader->setUniform4fv("lights["+idx+"].specular", &light->specularColor.r); currentShader->setUniform4fv("lights["+idx+"].diffuse", &light->diffuseColor.r); if(light->lightType==OF_LIGHT_POINT || light->lightType==OF_LIGHT_AREA){ currentShader->setUniform1f("lights["+idx+"].constantAttenuation", light->attenuation_constant); currentShader->setUniform1f("lights["+idx+"].linearAttenuation", light->attenuation_linear); currentShader->setUniform1f("lights["+idx+"].quadraticAttenuation", light->attenuation_quadratic); } if(light->lightType==OF_LIGHT_SPOT){ ofVec3f direction = light->position + light->direction; direction = direction * ofGetCurrentViewMatrix(); direction = direction - lightEyePosition; currentShader->setUniform3fv("lights["+idx+"].spotDirection", &direction.x); currentShader->setUniform1f("lights["+idx+"].spotExponent", light->exponent); currentShader->setUniform1f("lights["+idx+"].spotCutoff", light->spotCutOff); currentShader->setUniform1f("lights["+idx+"].spotCosCutoff", cos(ofDegToRad(light->spotCutOff))); }else if(light->lightType==OF_LIGHT_DIRECTIONAL){ ofVec3f halfVector = (ofVec3f(0,0,1) + lightEyePosition).getNormalized(); currentShader->setUniform3fv("lights["+idx+"].halfVector", &halfVector.x); }else if(light->lightType==OF_LIGHT_AREA){ currentShader->setUniform1f("lights["+idx+"].width", light->width); currentShader->setUniform1f("lights["+idx+"].height", light->height); ofVec3f direction = light->position + light->direction; direction = direction * ofGetCurrentViewMatrix(); direction = direction - lightEyePosition; ofVec3f right = light->position + light->right; right = right * ofGetCurrentViewMatrix(); right = right - lightEyePosition; ofVec3f up = right.getCrossed(direction); currentShader->setUniform3fv("lights["+idx+"].spotDirection", &direction.x); currentShader->setUniform3fv("lights["+idx+"].right", &right.x); currentShader->setUniform3fv("lights["+idx+"].up", &up.x); } } }
void ofMaterial::initShaders(ofGLProgrammableRenderer & renderer) const{ auto rendererShaders = shaders.find(&renderer); if(rendererShaders == shaders.end() || rendererShaders->second->numLights != ofLightsData().size()){ if(shadersMap[&renderer].find(data.postFragment)!=shadersMap[&renderer].end()){ auto newShaders = shadersMap[&renderer][data.postFragment].lock(); if(newShaders == nullptr || newShaders->numLights != ofLightsData().size()){ shadersMap[&renderer].erase(data.postFragment); shaders[&renderer] = nullptr; }else{ shaders[&renderer] = newShaders; } } } if(shaders[&renderer] == nullptr){ #ifndef TARGET_OPENGLES string vertexRectHeader = renderer.defaultVertexShaderHeader(GL_TEXTURE_RECTANGLE); string fragmentRectHeader = renderer.defaultFragmentShaderHeader(GL_TEXTURE_RECTANGLE); #endif string vertex2DHeader = renderer.defaultVertexShaderHeader(GL_TEXTURE_2D); string fragment2DHeader = renderer.defaultFragmentShaderHeader(GL_TEXTURE_2D); auto numLights = ofLightsData().size(); shaders[&renderer].reset(new Shaders); shaders[&renderer]->numLights = numLights; shaders[&renderer]->noTexture.setupShaderFromSource(GL_VERTEX_SHADER,vertexSource(vertex2DHeader,numLights,false,false)); shaders[&renderer]->noTexture.setupShaderFromSource(GL_FRAGMENT_SHADER,fragmentSource(fragment2DHeader, data.customUniforms, data.postFragment,numLights,false,false)); shaders[&renderer]->noTexture.bindDefaults(); shaders[&renderer]->noTexture.linkProgram(); shaders[&renderer]->texture2D.setupShaderFromSource(GL_VERTEX_SHADER,vertexSource(vertex2DHeader,numLights,true,false)); shaders[&renderer]->texture2D.setupShaderFromSource(GL_FRAGMENT_SHADER,fragmentSource(fragment2DHeader, data.customUniforms, data.postFragment,numLights,true,false)); shaders[&renderer]->texture2D.bindDefaults(); shaders[&renderer]->texture2D.linkProgram(); #ifndef TARGET_OPENGLES shaders[&renderer]->textureRect.setupShaderFromSource(GL_VERTEX_SHADER,vertexSource(vertexRectHeader,numLights,true,false)); shaders[&renderer]->textureRect.setupShaderFromSource(GL_FRAGMENT_SHADER,fragmentSource(fragmentRectHeader, data.customUniforms, data.postFragment,numLights,true,false)); shaders[&renderer]->textureRect.bindDefaults(); shaders[&renderer]->textureRect.linkProgram(); #endif shaders[&renderer]->color.setupShaderFromSource(GL_VERTEX_SHADER,vertexSource(vertex2DHeader,numLights,false,true)); shaders[&renderer]->color.setupShaderFromSource(GL_FRAGMENT_SHADER,fragmentSource(fragment2DHeader, data.customUniforms, data.postFragment,numLights,false,true)); shaders[&renderer]->color.bindDefaults(); shaders[&renderer]->color.linkProgram(); shaders[&renderer]->texture2DColor.setupShaderFromSource(GL_VERTEX_SHADER,vertexSource(vertex2DHeader,numLights,true,true)); shaders[&renderer]->texture2DColor.setupShaderFromSource(GL_FRAGMENT_SHADER,fragmentSource(fragment2DHeader, data.customUniforms, data.postFragment,numLights,true,true)); shaders[&renderer]->texture2DColor.bindDefaults(); shaders[&renderer]->texture2DColor.linkProgram(); #ifndef TARGET_OPENGLES shaders[&renderer]->textureRectColor.setupShaderFromSource(GL_VERTEX_SHADER,vertexSource(vertexRectHeader,numLights,true,true)); shaders[&renderer]->textureRectColor.setupShaderFromSource(GL_FRAGMENT_SHADER,fragmentSource(fragmentRectHeader, data.customUniforms, data.postFragment,numLights,true,true)); shaders[&renderer]->textureRectColor.bindDefaults(); shaders[&renderer]->textureRectColor.linkProgram(); #endif shadersMap[&renderer][data.postFragment] = shaders[&renderer]; } }