GLColorBuffer GLLensDustFilter::DownSample(GLColorBuffer tex,
												   bool linearize) {
			SPADES_MARK_FUNCTION();
			GLProgram *program = thru;
			IGLDevice *dev = renderer->GetGLDevice();
			GLQuadRenderer qr(dev);
			int w = tex.GetWidth();
			int h = tex.GetHeight();
			
			static GLProgramAttribute blur_positionAttribute("positionAttribute");
			static GLProgramUniform blur_textureUniform("mainTexture");
            static GLProgramUniform blur_colorUniform("colorUniform");
            static GLProgramUniform blur_texCoordRangeUniform("texCoordRange");
            static GLProgramUniform blur_texCoordOffsetUniform("texCoordOffset");
			program->Use();
			blur_positionAttribute(program);
			
			blur_textureUniform(program);
			blur_textureUniform.SetValue(0);
			dev->ActiveTexture(0);
			dev->BindTexture(IGLDevice::Texture2D, tex.GetTexture());
            
            blur_texCoordOffsetUniform(program);
            blur_texCoordOffsetUniform.SetValue(1.f / w, 1.f / h, -1.f / w, -1.f / h);
			
			blur_colorUniform(program);
			blur_colorUniform.SetValue(1.f,1.f,1.f,1.f);
			
			blur_texCoordRangeUniform(program);
			blur_texCoordRangeUniform.SetValue(0.f, 0.f,
                                               (float)((w + 1) & ~1) / w,
                                               (float)((h + 1) & ~1) / h);
			
			qr.SetCoordAttributeIndex(blur_positionAttribute());
			if(linearize){
				dev->Enable(IGLDevice::Blend, true);
				dev->BlendFunc(IGLDevice::SrcColor,
							   IGLDevice::Zero);
			}else{
				dev->Enable(IGLDevice::Blend, false);
			}
			
			GLColorBuffer buf2 = renderer->GetFramebufferManager()->CreateBufferHandle((w+1)/2, (h+1)/2, false);
			dev->Viewport(0, 0, buf2.GetWidth(), buf2.GetHeight());
			dev->BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer());
			qr.Draw();
			return buf2;
		}
		GLColorBuffer GLLensDustFilter::Filter(GLColorBuffer input) {
			SPADES_MARK_FUNCTION();
			
			UpdateNoise();
			
			std::vector<Level> levels;
			
			IGLDevice *dev = renderer->GetGLDevice();
			GLQuadRenderer qr(dev);
			
			static GLProgramAttribute thruPosition("positionAttribute");
			static GLProgramUniform thruColor("colorUniform");
			static GLProgramUniform thruTexture("mainTexture");
			static GLProgramUniform thruTexCoordRange("texCoordRange");
			
			thruPosition(thru);
			thruColor(thru);
			thruTexture(thru);
			thruTexCoordRange(thru);
						
			GLColorBuffer downSampled = DownSample(input, r_hdr ? false : true);
            downSampled = GaussianBlur(downSampled, false);
            downSampled = GaussianBlur(downSampled, true);
			
			thru->Use();
			thruColor.SetValue(1.f, 1.f, 1.f, 1.f);
			thruTexture.SetValue(0);
			dev->Enable(IGLDevice::Blend, false);
			
			levels.reserve(10);
			
			// create downsample levels
			for(int i = 0; i < 10; i++){
				GLColorBuffer prevLevel;
				if(i == 0){
					prevLevel = downSampled;
				}else{
					prevLevel = levels.back().buffer;
				}
				
				int prevW = prevLevel.GetWidth();
				int prevH = prevLevel.GetHeight();
				int newW = (prevW + 1) / 2;
				int newH = (prevH + 1) / 2;
				if(newW <= 1 || newH <= 1)
					break;
                GLColorBuffer newLevel = DownSample(prevLevel);
                newLevel = GaussianBlur(newLevel, false);
                newLevel = GaussianBlur(newLevel, true);
				
				Level lv;
				lv.w = newW; lv.h = newH;
				lv.buffer = newLevel;
				levels.push_back(lv);
			}
			
			dev->Enable(IGLDevice::Blend, true);
			dev->BlendFunc(IGLDevice::SrcAlpha,
						   IGLDevice::OneMinusSrcAlpha);
			
			// composite levels in the opposite direction
			thru->Use();
			qr.SetCoordAttributeIndex(thruPosition());
			for(int i = (int)levels.size() - 1; i >= 1; i--){
				int cnt = (int)levels.size() - i;
				float alpha = (float)cnt / (float)(cnt + 1);
                alpha = alpha;
				
				GLColorBuffer curLevel = levels[i].buffer;
				
				float sx = .25f / curLevel.GetWidth();
				float sy = .25f / curLevel.GetHeight();
				
				for(int j = 0; j < 4; j++) {
					if(i < (int)levels.size() - 1) {
						curLevel = levels[i].retBuf[j];
					}
					GLColorBuffer targLevel = levels[i - 1].buffer;
					GLColorBuffer targRet = input.GetManager()->CreateBufferHandle(targLevel.GetWidth(),
																	   targLevel.GetHeight(),
																	   false);
					levels[i - 1].retBuf[j] = targRet;
					
					dev->BindFramebuffer(IGLDevice::Framebuffer, targRet.GetFramebuffer());
					dev->Viewport(0, 0, targRet.GetWidth(), targRet.GetHeight());
					
					dev->BindTexture(IGLDevice::Texture2D, targLevel.GetTexture());
					thruColor.SetValue(1.f, 1.f, 1.f, 1.f);
					thruTexCoordRange.SetValue(0.f, 0.f, 1.f, 1.f);
					dev->Enable(IGLDevice::Blend, false);
					qr.Draw();
					
					float cx = 0.f, cy = 0.f;
					switch(j){
						case 0: cx = sx; break;
						case 1: cx = -sx; break;
						case 2: cy = sy; break;
						case 3: cy = -sy; break;
					}
					
					dev->BindTexture(IGLDevice::Texture2D, curLevel.GetTexture());
					thruColor.SetValue(1.f, 1.f, 1.f, alpha);
					thruTexCoordRange.SetValue(cx, cy, 1.f, 1.f);
					dev->Enable(IGLDevice::Blend, true);
					qr.Draw();
					
					dev->BindTexture(IGLDevice::Texture2D, 0);
				}
				
			}
			
			static GLProgramAttribute dustPosition("positionAttribute");
			static GLProgramUniform dustDustTexture("dustTexture");
			static GLProgramUniform dustBlurTexture1("blurTexture1");
			static GLProgramUniform dustBlurTexture2("blurTexture2");
			static GLProgramUniform dustBlurTexture3("blurTexture3");
			static GLProgramUniform dustBlurTexture4("blurTexture4");
			static GLProgramUniform dustInputTexture("inputTexture");
			static GLProgramUniform dustNoiseTexture("noiseTexture");
			static GLProgramUniform dustNoiseTexCoordFactor("noiseTexCoordFactor");
			
			dustPosition(dust);
			dustDustTexture(dust);
			dustBlurTexture1(dust);
			dustBlurTexture2(dust);
			dustBlurTexture3(dust);
			dustBlurTexture4(dust);
			dustInputTexture(dust);
			dustNoiseTexture(dust);
			dustNoiseTexCoordFactor(dust);
			
			dust->Use();
			
			float facX = renderer->ScreenWidth() / 128.f;
			float facY = renderer->ScreenHeight() / 128.f;
			dustNoiseTexCoordFactor.SetValue(facX, facY,
											 facX / 128.f,
											 facY / 128.f);
			
			// composite to the final image
			GLColorBuffer output = input.GetManager()->CreateBufferHandle();
			GLColorBuffer topLevel1 = levels[0].retBuf[0];
			GLColorBuffer topLevel2 = levels[0].retBuf[1];
			GLColorBuffer topLevel3 = levels[0].retBuf[2];
			GLColorBuffer topLevel4 = levels[0].retBuf[3];
			
			qr.SetCoordAttributeIndex(dustPosition());
			dev->ActiveTexture(0);
			dev->BindTexture(IGLDevice::Texture2D, input.GetTexture());
			dev->ActiveTexture(1);
			dev->BindTexture(IGLDevice::Texture2D, topLevel1.GetTexture());
			dev->ActiveTexture(2);
			dev->BindTexture(IGLDevice::Texture2D, topLevel2.GetTexture());
			dev->ActiveTexture(3);
			dev->BindTexture(IGLDevice::Texture2D, topLevel3.GetTexture());
			dev->ActiveTexture(4);
			dev->BindTexture(IGLDevice::Texture2D, topLevel4.GetTexture());
			dev->ActiveTexture(5);
			dustImg->Bind(IGLDevice::Texture2D);
			dev->ActiveTexture(6);
			dev->BindTexture(IGLDevice::Texture2D, noiseTex);
			dev->BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer());
			dev->Viewport(0, 0, output.GetWidth(), output.GetHeight());
			dustBlurTexture1.SetValue(2);
			dustBlurTexture2.SetValue(1);
			dustBlurTexture3.SetValue(3);
			dustBlurTexture4.SetValue(4);
			dustDustTexture.SetValue(5);
			dustNoiseTexture.SetValue(6);
			dustInputTexture.SetValue(0);
			qr.Draw();
			dev->BindTexture(IGLDevice::Texture2D, 0);
			
			dev->ActiveTexture(0);
			
			return output;
		}
Beispiel #3
0
		GLColorBuffer GLBloomFilter::Filter(GLColorBuffer input) {
			SPADES_MARK_FUNCTION();
			
			
			
			std::vector<Level> levels;
			
			IGLDevice *dev = renderer->GetGLDevice();
			GLQuadRenderer qr(dev);
			
			static GLProgramAttribute thruPosition("positionAttribute");
			static GLProgramUniform thruColor("colorUniform");
			static GLProgramUniform thruTexture("texture");
			static GLProgramUniform thruTexCoordRange("texCoordRange");
			
			thruPosition(thru);
			thruColor(thru);
			thruTexture(thru);
			thruTexCoordRange(thru);
			
			GLProgram *gammaMix = renderer->RegisterProgram("Shaders/PostFilters/GammaMix.program");
			static GLProgramAttribute gammaMixPosition("positionAttribute");
			static GLProgramUniform gammaMixTexture1("texture1");
			static GLProgramUniform gammaMixTexture2("texture2");
			static GLProgramUniform gammaMixMix1("mix1");
			static GLProgramUniform gammaMixMix2("mix2");
			
			gammaMixPosition(gammaMix);
			gammaMixTexture1(gammaMix);
			gammaMixTexture2(gammaMix);
			gammaMixMix1(gammaMix);
			gammaMixMix2(gammaMix);
			
			thru->Use();
			thruColor.SetValue(1.f, 1.f, 1.f, 1.f);
			thruTexture.SetValue(0);
			dev->Enable(IGLDevice::Blend, false);
			
			// create downsample levels
			for(int i = 0; i < 6; i++){
				GLColorBuffer prevLevel;
				if(i == 0){
					prevLevel = input;
				}else{
					prevLevel = levels.back().buffer;
				}
				
				int prevW = prevLevel.GetWidth();
				int prevH = prevLevel.GetHeight();
				int newW = (prevW + 1) / 2;
				int newH = (prevH + 1) / 2;
				GLColorBuffer newLevel = input.GetManager()->CreateBufferHandle(newW, newH);
				
				thru->Use();
				qr.SetCoordAttributeIndex(thruPosition());
				dev->BindTexture(IGLDevice::Texture2D, prevLevel.GetTexture());
				dev->BindFramebuffer(IGLDevice::Framebuffer, newLevel.GetFramebuffer());
				dev->Viewport(0, 0, newLevel.GetWidth(), newLevel.GetHeight());
				thruTexCoordRange.SetValue(0.f, 0.f,
										   (float)newLevel.GetWidth() * 2.f / (float)prevW,
										   (float)newLevel.GetHeight() * 2.f / (float)prevH);
				qr.Draw();
				dev->BindTexture(IGLDevice::Texture2D, 0);
				
				Level lv;
				lv.w = newW; lv.h = newH;
				lv.buffer = newLevel;
				levels.push_back(lv);
			}
			
			dev->Enable(IGLDevice::Blend, true);
			dev->BlendFunc(IGLDevice::SrcAlpha,
						   IGLDevice::OneMinusSrcAlpha);
			
			// composite levels in the opposite direction
			thruTexCoordRange.SetValue(0.f, 0.f, 1.f, 1.f);
			for(int i = (int)levels.size() - 1; i >= 1; i--){
				int cnt = (int)levels.size() - i;
				float alpha = (float)cnt / (float)(cnt + 1);
				alpha = sqrtf(alpha);
				GLColorBuffer curLevel = levels[i].buffer;
				GLColorBuffer targLevel = levels[i - 1].buffer;
			
				thru->Use();
				qr.SetCoordAttributeIndex(thruPosition());
				dev->BindTexture(IGLDevice::Texture2D, curLevel.GetTexture());
				dev->BindFramebuffer(IGLDevice::Framebuffer, targLevel.GetFramebuffer());
				dev->Viewport(0, 0, targLevel.GetWidth(), targLevel.GetHeight());
				thruColor.SetValue(1.f, 1.f, 1.f, alpha);
				qr.Draw();
				dev->BindTexture(IGLDevice::Texture2D, 0);
			}
			
			// composite to the final image
			GLColorBuffer output = input.GetManager()->CreateBufferHandle();
			GLColorBuffer topLevel = levels[0].buffer;
			
			gammaMix->Use();
			qr.SetCoordAttributeIndex(gammaMixPosition());
			dev->ActiveTexture(0);
			dev->BindTexture(IGLDevice::Texture2D, input.GetTexture());
			dev->ActiveTexture(1);
			dev->BindTexture(IGLDevice::Texture2D, topLevel.GetTexture());
			dev->BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer());
			dev->Viewport(0, 0, output.GetWidth(), output.GetHeight());
			gammaMixTexture1.SetValue(0);
			gammaMixTexture2.SetValue(1);
			gammaMixMix1.SetValue(.8f, .8f, .8f);
			gammaMixMix2.SetValue(.2f, .2f, .2f);
			qr.Draw();
			dev->BindTexture(IGLDevice::Texture2D, 0);
			
			dev->ActiveTexture(0);
			
			return output;
		}