def make_buffer(self, name: str, shader_path: str, clear_color=0.0): buffer = self.panda3d.win.makeTextureBuffer(name, 0, 0) color = LVecBase4(clear_color) buffer.setClearColor(color) camera_lens = self.panda3d.cam.node().getLens() camera = self.panda3d.makeCamera(buffer, lens=camera_lens) camera.node().setScene(self.panda3d.render) temp_node = NodePath(PandaNode("node " + name)) shader = self.panda3d.loader.loadShader(shader_path) temp_node.setShader(shader) temp_node.setShaderInput("showborders", LVecBase4(1)) temp_node.setShaderInput("colorborders", LVecBase4(0, 0, 0, 1)) camera.node().setInitialState(temp_node.getState()) return buffer, camera
def update(self, task=None): if 'VolumetricLighting' in self.configuration: caster = self.configuration['VolumetricLighting'].caster casterpos = LPoint2() self.manager.camera.node().getLens().project( caster.getPos(self.manager.camera), casterpos) self.finalQuad.setShaderInput( 'casterpos', LVecBase4(casterpos.getX() * 0.5 + 0.5, casterpos.getY() * 0.5 + 0.5, 0, 0)) if task != None: return task.cont return
def loadShaders(): normalsBuffer = base.win.makeTextureBuffer("normalsBuffer", 0, 0) normalsBuffer.setClearColor(LVecBase4(0.5, 0.5, 0.5, 1)) normalsBuffer = normalsBuffer normalsCamera = base.makeCamera(normalsBuffer, lens=base.cam.node().getLens()) normalsCamera.node().setScene(render) drawnScene = normalsBuffer.getTextureCard() drawnScene.setTransparency(1) drawnScene.setColor(1, 1, 1, 0) drawnScene.reparentTo(render2d) print("loading shaders...") return drawnScene
def update(self, task=None): """Updates the shader inputs that need to be updated every frame. Normally, you shouldn't call this, it's being called in a task.""" if "VolumetricLighting" in self.configuration: caster = self.configuration["VolumetricLighting"].caster casterpos = LPoint2() self.manager.camera.node().getLens().project( caster.getPos(self.manager.camera), casterpos) self.finalQuad.setShaderInput( "casterpos", LVecBase4(casterpos.getX() * 0.5 + 0.5, (casterpos.getY() * 0.5 + 0.5), 0, 0)) if task != None: return task.cont
def reconfigure(self, fullrebuild, changed): """ Reconfigure is called whenever any configuration change is made. """ configuration = self.configuration if (fullrebuild): self.cleanup() if (len(configuration) == 0): return auxbits = 0 needtex = set(["color"]) needtexcoord = set(["color"]) if ("CartoonInk" in configuration): needtex.add("aux") auxbits |= AuxBitplaneAttrib.ABOAuxNormal needtexcoord.add("aux") if ("AmbientOcclusion" in configuration): needtex.add("depth") needtex.add("ssao0") needtex.add("ssao1") needtex.add("ssao2") needtex.add("aux") auxbits |= AuxBitplaneAttrib.ABOAuxNormal needtexcoord.add("ssao2") if ("BlurSharpen" in configuration): needtex.add("blur0") needtex.add("blur1") needtexcoord.add("blur1") if ("Bloom" in configuration): needtex.add("bloom0") needtex.add("bloom1") needtex.add("bloom2") needtex.add("bloom3") auxbits |= AuxBitplaneAttrib.ABOGlow needtexcoord.add("bloom3") if ("ViewGlow" in configuration): auxbits |= AuxBitplaneAttrib.ABOGlow if ("VolumetricLighting" in configuration): needtex.add(configuration["VolumetricLighting"].source) for tex in needtex: self.textures[tex] = Texture("scene-" + tex) self.textures[tex].setWrapU(Texture.WMClamp) self.textures[tex].setWrapV(Texture.WMClamp) self.finalQuad = self.manager.renderSceneInto( textures=self.textures, auxbits=auxbits) if (self.finalQuad == None): self.cleanup() return False if ("BlurSharpen" in configuration): blur0 = self.textures["blur0"] blur1 = self.textures["blur1"] self.blur.append( self.manager.renderQuadInto(colortex=blur0, div=2)) self.blur.append(self.manager.renderQuadInto(colortex=blur1)) self.blur[0].setShaderInput("src", self.textures["color"]) self.blur[0].setShader(self.loadShader("filter-blurx.sha")) self.blur[1].setShaderInput("src", blur0) self.blur[1].setShader(self.loadShader("filter-blury.sha")) if ("AmbientOcclusion" in configuration): ssao0 = self.textures["ssao0"] ssao1 = self.textures["ssao1"] ssao2 = self.textures["ssao2"] self.ssao.append(self.manager.renderQuadInto(colortex=ssao0)) self.ssao.append( self.manager.renderQuadInto(colortex=ssao1, div=2)) self.ssao.append(self.manager.renderQuadInto(colortex=ssao2)) self.ssao[0].setShaderInput("depth", self.textures["depth"]) self.ssao[0].setShaderInput("normal", self.textures["aux"]) self.ssao[0].setShaderInput( "random", loader.loadTexture("maps/random.rgb")) self.ssao[0].setShader( Shader.make( SSAO_BODY % configuration["AmbientOcclusion"].numsamples, Shader.SL_Cg)) self.ssao[1].setShaderInput("src", ssao0) self.ssao[1].setShader(self.loadShader("filter-blurx.sha")) self.ssao[2].setShaderInput("src", ssao1) self.ssao[2].setShader(self.loadShader("filter-blury.sha")) if ("Bloom" in configuration): bloomconf = configuration["Bloom"] bloom0 = self.textures["bloom0"] bloom1 = self.textures["bloom1"] bloom2 = self.textures["bloom2"] bloom3 = self.textures["bloom3"] if (bloomconf.size == "large"): scale = 8 downsampler = "filter-down4.sha" elif (bloomconf.size == "medium"): scale = 4 downsampler = "filter-copy.sha" else: scale = 2 downsampler = "filter-copy.sha" self.bloom.append( self.manager.renderQuadInto(colortex=bloom0, div=2, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom1, div=scale, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom2, div=scale, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom3, div=scale, align=scale)) self.bloom[0].setShaderInput("src", self.textures["color"]) self.bloom[0].setShader(self.loadShader("filter-bloomi.sha")) self.bloom[1].setShaderInput("src", bloom0) self.bloom[1].setShader(self.loadShader(downsampler)) self.bloom[2].setShaderInput("src", bloom1) self.bloom[2].setShader(self.loadShader("filter-bloomx.sha")) self.bloom[3].setShaderInput("src", bloom2) self.bloom[3].setShader(self.loadShader("filter-bloomy.sha")) texcoords = {} texcoordPadding = {} for tex in needtexcoord: if self.textures[tex].getAutoTextureScale() != ATSNone or \ "HalfPixelShift" in configuration: texcoords[tex] = "l_texcoord_" + tex texcoordPadding["l_texcoord_" + tex] = tex else: # Share unpadded texture coordinates. texcoords[tex] = "l_texcoord" texcoordPadding["l_texcoord"] = None texcoordSets = list(enumerate(texcoordPadding.keys())) text = "//Cg\n" text += "void vshader(float4 vtx_position : POSITION,\n" text += " out float4 l_position : POSITION,\n" for texcoord, padTex in texcoordPadding.items(): if padTex is not None: text += " uniform float4 texpad_tx%s,\n" % (padTex) if ("HalfPixelShift" in configuration): text += " uniform float4 texpix_tx%s,\n" % (padTex) for i, name in texcoordSets: text += " out float2 %s : TEXCOORD%d,\n" % (name, i) text += " uniform float4x4 mat_modelproj)\n" text += "{\n" text += " l_position = mul(mat_modelproj, vtx_position);\n" for texcoord, padTex in texcoordPadding.items(): if padTex is None: text += " %s = vtx_position.xz * float2(0.5, 0.5) + float2(0.5, 0.5);\n" % ( texcoord) else: text += " %s = (vtx_position.xz * texpad_tx%s.xy) + texpad_tx%s.xy;\n" % ( texcoord, padTex, padTex) if ("HalfPixelShift" in configuration): text += " %s += texpix_tx%s.xy * 0.5;\n" % (texcoord, padTex) text += "}\n" text += "void fshader(\n" for i, name in texcoordSets: text += " float2 %s : TEXCOORD%d,\n" % (name, i) for key in self.textures: text += " uniform sampler2D k_tx" + key + ",\n" if ("CartoonInk" in configuration): text += " uniform float4 k_cartoonseparation,\n" text += " uniform float4 k_cartooncolor,\n" text += " uniform float4 texpix_txaux,\n" if ("BlurSharpen" in configuration): text += " uniform float4 k_blurval,\n" if ("VolumetricLighting" in configuration): text += " uniform float4 k_casterpos,\n" text += " uniform float4 k_vlparams,\n" text += " out float4 o_color : COLOR)\n" text += "{\n" text += " o_color = tex2D(k_txcolor, %s);\n" % ( texcoords["color"]) if ("CartoonInk" in configuration): text += CARTOON_BODY % {"texcoord": texcoords["aux"]} if ("AmbientOcclusion" in configuration): text += " o_color *= tex2D(k_txssao2, %s).r;\n" % ( texcoords["ssao2"]) if ("BlurSharpen" in configuration): text += " o_color = lerp(tex2D(k_txblur1, %s), o_color, k_blurval.x);\n" % ( texcoords["blur1"]) if ("Bloom" in configuration): text += " o_color = saturate(o_color);\n" text += " float4 bloom = 0.5 * tex2D(k_txbloom3, %s);\n" % ( texcoords["bloom3"]) text += " o_color = 1-((1-bloom)*(1-o_color));\n" if ("ViewGlow" in configuration): text += " o_color.r = o_color.a;\n" if ("VolumetricLighting" in configuration): text += " float decay = 1.0f;\n" text += " float2 curcoord = %s;\n" % (texcoords["color"]) text += " float2 lightdir = curcoord - k_casterpos.xy;\n" text += " lightdir *= k_vlparams.x;\n" text += " half4 sample = tex2D(k_txcolor, curcoord);\n" text += " float3 vlcolor = sample.rgb * sample.a;\n" text += " for (int i = 0; i < %s; i++) {\n" % (int( configuration["VolumetricLighting"].numsamples)) text += " curcoord -= lightdir;\n" text += " sample = tex2D(k_tx%s, curcoord);\n" % ( configuration["VolumetricLighting"].source) text += " sample *= sample.a * decay;//*weight\n" text += " vlcolor += sample.rgb;\n" text += " decay *= k_vlparams.y;\n" text += " }\n" text += " o_color += float4(vlcolor * k_vlparams.z, 1);\n" if ("GammaAdjust" in configuration): gamma = configuration["GammaAdjust"] if gamma == 0.5: text += " o_color.rgb = sqrt(o_color.rgb);\n" elif gamma == 2.0: text += " o_color.rgb *= o_color.rgb;\n" elif gamma != 1.0: text += " o_color.rgb = pow(o_color.rgb, %ff);\n" % ( gamma) if ("Inverted" in configuration): text += " o_color = float4(1, 1, 1, 1) - o_color;\n" text += "}\n" self.finalQuad.setShader(Shader.make(text, Shader.SL_Cg)) for tex in self.textures: self.finalQuad.setShaderInput("tx" + tex, self.textures[tex]) self.task = taskMgr.add(self.update, "common-filters-update") if (changed == "CartoonInk") or fullrebuild: if ("CartoonInk" in configuration): c = configuration["CartoonInk"] self.finalQuad.setShaderInput( "cartoonseparation", LVecBase4(c.separation, 0, c.separation, 0)) self.finalQuad.setShaderInput("cartooncolor", c.color) if (changed == "BlurSharpen") or fullrebuild: if ("BlurSharpen" in configuration): blurval = configuration["BlurSharpen"] self.finalQuad.setShaderInput( "blurval", LVecBase4(blurval, blurval, blurval, blurval)) if (changed == "Bloom") or fullrebuild: if ("Bloom" in configuration): bloomconf = configuration["Bloom"] intensity = bloomconf.intensity * 3.0 self.bloom[0].setShaderInput("blend", bloomconf.blendx, bloomconf.blendy, bloomconf.blendz, bloomconf.blendw * 2.0) self.bloom[0].setShaderInput( "trigger", bloomconf.mintrigger, 1.0 / (bloomconf.maxtrigger - bloomconf.mintrigger), 0.0, 0.0) self.bloom[0].setShaderInput("desat", bloomconf.desat) self.bloom[3].setShaderInput("intensity", intensity, intensity, intensity, intensity) if (changed == "VolumetricLighting") or fullrebuild: if ("VolumetricLighting" in configuration): config = configuration["VolumetricLighting"] tcparam = config.density / float(config.numsamples) self.finalQuad.setShaderInput("vlparams", tcparam, config.decay, config.exposure, 0.0) if (changed == "AmbientOcclusion") or fullrebuild: if ("AmbientOcclusion" in configuration): config = configuration["AmbientOcclusion"] self.ssao[0].setShaderInput( "params1", config.numsamples, -float(config.amount) / config.numsamples, config.radius, 0) self.ssao[0].setShaderInput("params2", config.strength, config.falloff, 0, 0) self.update() return True
def renderShaders(app): app.render.setShaderInput("tint", LVector4f(1.0, 0.5, 0.5, 1.0)) # Check video card capabilities. if not app.win.getGsg().getSupportsBasicShaders(): OnscreenText( "Toon Shader: Video driver reports that Cg shaders are not supported." ) return # This shader's job is to render the model with discrete lighting # levels. The lighting calculations built into the shader assume # a single nonattenuating point light. # tempnode = NodePath(PandaNode("temp node")) app.parentNode.setShader(app.loader.loadShader("Lighting/lightingGen.sha")) app.cam.node().setInitialState(app.parentNode.getState()) # This is the object that represents the single "light", as far # the shader is concerned. It's not a real Panda3D LightNode, but # the shader doesn't care about that. light = app.render.attachNewNode("light") light.setPos(30, -50, 0) # this call puts the light's nodepath into the render state. # this enables the shader to access this light by name. app.render.setShaderInput("light", light) # The "normals buffer" will contain a picture of the model colorized # so that the color of the model is a representation of the model's # normal at that point. normalsBuffer = app.win.makeTextureBuffer("normalsBuffer", 0, 0) normalsBuffer.setClearColor(LVecBase4(0.5, 0.5, 0.5, 1)) app.normalsBuffer = normalsBuffer normalsCamera = app.makeCamera(normalsBuffer, lens=app.cam.node().getLens()) normalsCamera.reparentTo(app.cam) normalsCamera.lookAt(app.parentNode) normalsCamera.node().setScene(app.render) tempnode = NodePath(PandaNode("temp node")) tempnode.setShader(app.loader.loadShader("Lighting/normalGen.sha")) normalsCamera.node().setInitialState(tempnode.getState()) # normalsCamera.node().reparentTo(app.parentNode) # what we actually do to put edges on screen is apply them as a texture to # a transparent screen-fitted card drawnScene = normalsBuffer.getTextureCard() drawnScene.setTransparency(1) drawnScene.setColor(1, 1, 1, 0) drawnScene.reparentTo(app.render2d) app.drawnScene = drawnScene # this shader accepts, as input, the picture from the normals buffer. # it compares each adjacent pixel, looking for discontinuities. # wherever a discontinuity exists, it emits black ink. app.separation = 0.001 app.cutoff = 0.3 inkGen = app.loader.loadShader("Lighting/inkGen.sha") drawnScene.setShader(inkGen) drawnScene.setShaderInput("separation", LVecBase4(app.separation, 0, app.separation, 0)) drawnScene.setShaderInput("cutoff", LVecBase4(app.cutoff)) # Panda contains a built-in viewer that lets you view the results of # your render-to-texture operations. This code configures the viewer. app.accept("v", app.bufferViewer.toggleEnable) app.accept("V", app.bufferViewer.toggleEnable) app.bufferViewer.setPosition("llcorner")
def reconfigure(self, fullrebuild, changed): """ Reconfigure is called whenever any configuration change is made. """ configuration = self.configuration if (fullrebuild): self.cleanup() if not self.manager.win.gsg.getSupportsBasicShaders(): return False auxbits = 0 # Color texture is already created at init, # we don't need to make it. needtex = set() needtexcoord = set(["color"]) if ("SSR" in configuration): needtex.add("depth") needtex.add("aux0") needtex.add("aux1") needtex.add("ssrreflection") auxbits |= (AUXBITS_NORMAL | AUXBITS_ARME) # aux glow for ARME if ("AmbientOcclusion" in configuration): needtex.add("depth") needtex.add("ssao0") needtex.add("ssao1") needtex.add("ssao2") if ("DOF" in configuration): needtex.add("blur0") needtex.add("blur1") if ("DOF" in configuration): needtex.add("depth") if ("FXAA" in configuration): needtex.add("fxaa") if ("Bloom" in configuration): needtex.add("bloom0") needtex.add("bloom1") needtex.add("bloom2") needtex.add("bloom3") for tex in needtex: self.makeTexture(tex) self.finalQuad = self.manager.renderSceneInto(textures = self.textures, auxbits=auxbits) if (self.finalQuad == None): self.cleanup() return False if ("SSR" in configuration): self.ssr.append(self.manager.renderQuadInto("ssr-reflection", colortex = self.textures["ssrreflection"])) self.ssr[0].setShader(Shader.load(Shader.SL_GLSL, "resources/phase_14/models/shaders/ssr.vert.glsl", "resources/phase_14/models/shaders/ssr_reflection.frag.glsl")) self.ssr[0].setShaderInput("colorSampler", self.textures["color"]) self.ssr[0].setShaderInput("depthSampler", self.textures["depth"]) self.ssr[0].setShaderInput("normalSampler", self.textures["aux0"]) self.ssr[0].setShaderInput("armeSampler", self.textures["aux1"]) if ("FXAA" in configuration): fxaa=self.textures["fxaa"] self.fxaa = self.manager.renderQuadInto(colortex=fxaa) self.fxaa.setShader(Shader.load(Shader.SL_GLSL, "phase_14/models/shaders/fxaa.vert.glsl", "phase_14/models/shaders/fxaa.frag.glsl")) self.fxaa.setShaderInput("sceneTexture", self.textures["color"]) if ("AmbientOcclusion" in configuration): ssao0=self.textures["ssao0"] ssao1=self.textures["ssao1"] ssao2=self.textures["ssao2"] self.ssao.append(self.manager.renderQuadInto(colortex=ssao0)) self.ssao.append(self.manager.renderQuadInto(colortex=ssao1,div=2)) self.ssao.append(self.manager.renderQuadInto(colortex=ssao2)) self.ssao[0].setShaderInput("depthSampler", self.textures["depth"]) self.ssao[0].setShader(Shader.make(Shader.SL_GLSL, SSAO_VERT, SSAO_PIXEL)) self.ssao[1].setShaderInput("src", ssao0) self.ssao[1].setShader(self.loadShader("phase_3/models/shaders/filter-blurx.sha")) self.ssao[2].setShaderInput("src", ssao1) self.ssao[2].setShader(self.loadShader("phase_3/models/shaders/filter-blury.sha")) if ("DOF" in configuration): blur0=self.textures["blur0"] blur1=self.textures["blur1"] self.blur.append(self.manager.renderQuadInto(colortex=blur0,div=2)) self.blur.append(self.manager.renderQuadInto(colortex=blur1)) self.blur[0].setShaderInput("src", self.textures["color"]) self.blur[0].setShader(self.loadShader("phase_3/models/shaders/filter-blurx.sha")) self.blur[1].setShaderInput("src", blur0) self.blur[1].setShader(self.loadShader("phase_3/models/shaders/filter-blury.sha")) if ("Bloom" in configuration): bloomconf = configuration["Bloom"] bloom0=self.textures["bloom0"] bloom1=self.textures["bloom1"] bloom2=self.textures["bloom2"] bloom3=self.textures["bloom3"] if (bloomconf.size == "large"): scale=8 downsampler="phase_3/models/shaders/filter-down4.sha" elif (bloomconf.size == "medium"): scale=4 downsampler="phase_3/models/shaders/filter-copy.sha" else: scale=2 downsampler="phase_3/models/shaders/filter-copy.sha" self.bloom.append(self.manager.renderQuadInto(colortex=bloom0, div=2, align=scale)) self.bloom.append(self.manager.renderQuadInto(colortex=bloom1, div=scale, align=scale)) self.bloom.append(self.manager.renderQuadInto(colortex=bloom2, div=scale, align=scale)) self.bloom.append(self.manager.renderQuadInto(colortex=bloom3, div=scale, align=scale)) self.bloom[0].setShaderInput("src", self.textures["color"]) self.bloom[0].setShader(self.loadShader("phase_3/models/shaders/filter-bloomi.sha")) self.bloom[1].setShaderInput("src", bloom0) self.bloom[1].setShader(self.loadShader(downsampler)) self.bloom[2].setShaderInput("src", bloom1) self.bloom[2].setShader(self.loadShader("phase_3/models/shaders/filter-bloomx.sha")) self.bloom[3].setShaderInput("src", bloom2) self.bloom[3].setShader(self.loadShader("phase_3/models/shaders/filter-bloomy.sha")) vtext = "#version 330\n" vtext += "uniform mat4 p3d_ModelViewProjectionMatrix;\n" vtext += "in vec4 p3d_Vertex;\n" vtext += "in vec4 texcoord;\n" vtext += "out vec2 l_texcoord;\n" vtext += "void main()\n" vtext += "{\n" vtext += " gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;\n" vtext += " l_texcoord = texcoord.xy;\n" vtext += "}\n" ptext = "#version 330\n" ptext += "out vec4 outputColor;\n" ptext += "in vec2 l_texcoord;\n" for key in self.textures: ptext += "uniform sampler2D tx_" + key + ";\n" if ("DOF" in configuration): ptext += "uniform vec4 dofParams;\n" ptext += "void main()\n" ptext += "{\n" if ("FXAA" in configuration): ptext += " vec4 result = texture(tx_fxaa, l_texcoord);\n" else: ptext += " vec4 result = texture(tx_color, l_texcoord);\n" if ("AmbientOcclusion" in configuration): ptext += " result *= texture(tx_ssao2, l_texcoord).r;\n" if ("SSR" in configuration): ptext += " result.rgb += texture(tx_ssrreflection, l_texcoord).rgb;\n" if ("DOF" in configuration): ptext += " float blurFactor;\n" ptext += " float distance = dofParams.x;\n" ptext += " float range = dofParams.y;\n" ptext += " float near = dofParams.z;\n" ptext += " float far = dofParams.w;\n" ptext += " float depth = texture(tx_depth, l_texcoord).r;\n" ptext += " float sceneZ = (-near * far) / (depth - far);\n" ptext += " blurFactor = 1 - clamp(abs(sceneZ - distance) / range, 0, 1);\n" ptext += " result = mix(texture(tx_blur1, l_texcoord), result, blurFactor);\n" if ("Bloom" in configuration): ptext += " vec3 bloom = texture(tx_bloom3, l_texcoord).rgb;\n" ptext += " result.rgb += bloom.rgb;\n" ptext += " outputColor = result;\n" ptext += "}\n" shader = Shader.make(Shader.SL_GLSL, vtext, ptext) if not shader: return False self.finalQuad.setShader(shader) for tex in self.textures: self.finalQuad.setShaderInput("tx_"+tex, self.textures[tex]) self.task = taskMgr.add(self.update, "common-filters-update") messenger.send("CICommonFilters_reconfigure") if (changed == "SSR") or fullrebuild: if ("SSR" in configuration): ssrconf = configuration["SSR"] self.ssr[0].setShaderInput("camera", self.manager.camera) self.ssr[0].setShaderInput("params", ssrconf.reflParams) if (changed == "DOF") or fullrebuild: if ("DOF" in configuration): conf = configuration["DOF"] self.finalQuad.setShaderInput("dofParams", LVecBase4(conf.distance, conf.range, conf.near, conf.far)) if (changed == "Bloom") or fullrebuild: if ("Bloom" in configuration): bloomconf = configuration["Bloom"] intensity = bloomconf.intensity * 3.0 self.bloom[0].setShaderInput("blend", bloomconf.blendx, bloomconf.blendy, bloomconf.blendz, bloomconf.blendw * 2.0) self.bloom[0].setShaderInput("trigger", bloomconf.mintrigger, 1.0/(bloomconf.maxtrigger-bloomconf.mintrigger), 0.0, 0.0) self.bloom[0].setShaderInput("desat", bloomconf.desat) self.bloom[3].setShaderInput("intensity", intensity, intensity, intensity, intensity) if (changed == "AmbientOcclusion") or fullrebuild: if ("AmbientOcclusion" in configuration): config = configuration["AmbientOcclusion"] self.ssao[0].setShaderInput("totalStrength", config.totalStrength) self.ssao[0].setShaderInput("base", config.base) self.ssao[0].setShaderInput("area", config.area) self.ssao[0].setShaderInput("falloff", config.falloff) self.ssao[0].setShaderInput("numSamples", config.numsamples) self.ssao[0].setShaderInput("radius", config.radius) self.update() return True
def region_to_uv(self, region): flt = LVecBase4(region.x, region.y, region.z, region.w) return flt * (self._tile_size / self._size)
def __init__(self): # Initialize the ShowBase class from which we inherit, which will # create a window and set up everything we need for rendering into it. ShowBase.__init__(self) self.disableMouse() camera.setPos(0, -50, 0) # Check video card capabilities. if not self.win.getGsg().getSupportsBasicShaders(): addTitle( "Toon Shader: Video driver reports that Cg shaders are not supported." ) return # Show instructions in the corner of the window. self.title = addTitle( "Panda3D: Tutorial - Toon Shading with Normals-Based Inking") self.inst1 = addInstructions(0.06, "ESC: Quit") self.inst2 = addInstructions( 0.12, "Up/Down: Increase/Decrease Line Thickness") self.inst3 = addInstructions( 0.18, "Left/Right: Decrease/Increase Line Darkness") self.inst4 = addInstructions(0.24, "V: View the render-to-texture results") # This shader's job is to render the model with discrete lighting # levels. The lighting calculations built into the shader assume # a single nonattenuating point light. tempnode = NodePath(PandaNode("temp node")) tempnode.setShader(loader.loadShader("lightingGen.sha")) self.cam.node().setInitialState(tempnode.getState()) # This is the object that represents the single "light", as far # the shader is concerned. It's not a real Panda3D LightNode, but # the shader doesn't care about that. light = render.attachNewNode("light") light.setPos(30, -50, 0) # this call puts the light's nodepath into the render state. # this enables the shader to access this light by name. render.setShaderInput("light", light) # The "normals buffer" will contain a picture of the model colorized # so that the color of the model is a representation of the model's # normal at that point. normalsBuffer = self.win.makeTextureBuffer("normalsBuffer", 0, 0) normalsBuffer.setClearColor(LVecBase4(0.5, 0.5, 0.5, 1)) self.normalsBuffer = normalsBuffer normalsCamera = self.makeCamera(normalsBuffer, lens=self.cam.node().getLens()) normalsCamera.node().setScene(render) tempnode = NodePath(PandaNode("temp node")) tempnode.setShader(loader.loadShader("normalGen.sha")) normalsCamera.node().setInitialState(tempnode.getState()) # what we actually do to put edges on screen is apply them as a texture to # a transparent screen-fitted card drawnScene = normalsBuffer.getTextureCard() drawnScene.setTransparency(1) drawnScene.setColor(1, 1, 1, 0) drawnScene.reparentTo(render2d) self.drawnScene = drawnScene # this shader accepts, as input, the picture from the normals buffer. # it compares each adjacent pixel, looking for discontinuities. # wherever a discontinuity exists, it emits black ink. self.separation = 0.001 self.cutoff = 0.3 inkGen = loader.loadShader("inkGen.sha") drawnScene.setShader(inkGen) drawnScene.setShaderInput( "separation", LVecBase4(self.separation, 0, self.separation, 0)) drawnScene.setShaderInput("cutoff", LVecBase4(self.cutoff)) # Panda contains a built-in viewer that lets you view the results of # your render-to-texture operations. This code configures the viewer. self.accept("v", self.bufferViewer.toggleEnable) self.accept("V", self.bufferViewer.toggleEnable) self.bufferViewer.setPosition("llcorner") # Load a dragon model and start its animation. self.character = Actor() self.character.loadModel('models/nik-dragon') self.character.reparentTo(render) self.character.loop('win') self.character.hprInterval(15, (360, 0, 0)).loop() # These allow you to change cartooning parameters in realtime self.accept("escape", sys.exit, [0]) self.accept("arrow_up", self.increaseSeparation) self.accept("arrow_down", self.decreaseSeparation) self.accept("arrow_left", self.increaseCutoff) self.accept("arrow_right", self.decreaseCutoff)
from panda3d.core import AmbientLight from panda3d.core import Vec4, Mat4, Point3, Point4, BitMask32 from panda3d.core import LineSegs, NodePath from panda3d.core import LVecBase4, LVecBase2d, InputDevice from pandac.PandaModules import WindowProperties from direct.gui.OnscreenText import OnscreenText from direct.interval.LerpInterval import LerpPosInterval arrow_right = KeyboardButton.right() arrow_left = KeyboardButton.left() arrow_back = KeyboardButton.down() arrow_forward = KeyboardButton.up() GG = LVecBase4(0, 1, 0, 1) # game green constant camera_dict = {"turn_ang_vel": 0.25, "translate_vel": 0.5} NUMET = 2 # number of enemy tanks tanks_dict = { "0": {}, "1": { "init_pos": Point3(30, 50, 0), "color_scale": Point4(0, 0.7, 0, 1.0), "move_params": { "Ax": 25, "Ay": 18, "Bx": -0.15, "By": 0.25, "phix": 10, "phiy": 0 },
def __init__(self): # Initialize the ShowBase class from which we inherit, which will # create a window and set up everything we need for rendering into it. ShowBase.__init__(self) ''' cam1 = Camera('cam1') cam1.getLens().setNear(0.01) cam1.getLens().setFov(50) cam1.showFrustum() camera1 = self.render.attachNewNode(cam1) camera1.setName('camera1') camera1.setPos(0, -6, 3) cam2 = Camera('cam2') cam2.getLens().setNear(0.01) cam2.getLens().setFov(50) #cam2.showFrustum() camera2 = self.render.attachNewNode(cam2) camera2.setName('camera2') camera2.setPos(0, -6, 3) ''' self.disableMouse() #self.cam = camera2 #self.lens = self.cam.node().getLens() self.camera.setPos(0, -6, 3.2) self.camLens.setNearFar(0.01, 1000.0) self.camLens.setFov(50) #self.cam.node().setLodScale(math.tan(math.radians(100.0 * 0.5))) self.setBackgroundColor(1, 1, 1) # Check video card capabilities. if not self.win.getGsg().getSupportsBasicShaders(): print( "Toon Shader: Video driver reports that Cg shaders are not supported." ) return # This shader's job is to render the model with discrete lighting # levels. The lighting calculations built into the shader assume # a single nonattenuating point light. tempnode = NodePath(PandaNode("temp node")) tempnode.setShader(self.loader.loadShader("shader/lightingGen.sha")) self.cam.node().setInitialState(tempnode.getState()) # This is the object that represents the single "light", as far # the shader is concerned. It's not a real Panda3D LightNode, but # the shader doesn't care about that. light = self.render.attachNewNode("light") light.setPos(30, -50, 0) # this call puts the light's nodepath into the render state. # this enables the shader to access this light by name. self.render.setShaderInput("light", light) # The "normals buffer" will contain a picture of the model colorized # so that the color of the model is a representation of the model's # normal at that point. normalsBuffer = self.win.makeTextureBuffer("normalsBuffer", 0, 0) normalsBuffer.setClearColor(LVecBase4(0.5, 0.5, 0.5, 1)) self.normalsBuffer = normalsBuffer normalsCamera = self.makeCamera(normalsBuffer, lens=self.cam.node().getLens()) normalsCamera.node().setScene(self.render) tempnode = NodePath(PandaNode("temp node")) tempnode.setShader(self.loader.loadShader("shader/normalGen.sha")) normalsCamera.node().setInitialState(tempnode.getState()) # what we actually do to put edges on screen is apply them as a texture to # a transparent screen-fitted card drawnScene = normalsBuffer.getTextureCard() drawnScene.setTransparency(1) drawnScene.setColor(1, 1, 1, 0) drawnScene.reparentTo(self.render2d) self.drawnScene = drawnScene # this shader accepts, as input, the picture from the normals buffer. # it compares each adjacent pixel, looking for discontinuities. # wherever a discontinuity exists, it emits black ink. self.separation = 0.00065 self.cutoff = 0.3 inkGen = self.loader.loadShader("shader/inkGen.sha") drawnScene.setShader(inkGen) drawnScene.setShaderInput( "separation", LVecBase4(self.separation, 0, self.separation, 0)) drawnScene.setShaderInput("cutoff", LVecBase4(self.cutoff)) # Load a model and start its animation. self.character = Actor() #self.character.loadModel('models/miku/tda_miku') #self.character.loadAnims({'anim': 'models/miku/tda_miku-Anim0'}) #self.character.listJoints() #node = self.character.find('**/*modelRoot') #geom_node = node.getChildren()[0].node() #geoms = geom_node.getGeoms() #for child in node.getChildren(): # print child self.character.loadModel('models/dekiruo/dekiruo') self.character.reparentTo(self.render) self.character.ls() self.character.loadAnims( {'normal': 'models/dekiruo/dekiruo-Anim_normal'}) self.character.play('normal') #self.character.loadAnims({'anger': 'models/dekiruo/dekiruo-Anim_anger'}) #self.character.play('anger') #self.character.loadAnims({'sadness2crying': 'models/dekiruo/dekiruo-Anim_sadness2crying'}) #self.character.play('sadness2crying') #self.character.loadAnims({'sleep': 'models/dekiruo/dekiruo-Anim_sleep'}) #self.character.play('sleep') #self.character.loadAnims({'smile': 'models/dekiruo/dekiruo-Anim_smile'}) #self.character.play('smile') #self.character.loadAnims({'surprised': 'models/dekiruo/dekiruo-Anim_surprised'}) #self.character.play('surprised') #self.character.loadModel('models/dekinaio/dekinaio') #self.character.reparentTo(self.render) #self.character.ls() #self.character.loadAnims({'normal': 'models/dekinaio/dekinaio-Anim_normal'}) #self.character.play('normal') #self.character.loadAnims({'anger': 'models/dekinaio/dekinaio-Anim_anger'}) #self.character.play('anger') #self.character.loadAnims({'sadness2crying': 'models/dekinaio/dekinaio-Anim_sadness2crying'}) #self.character.play('sadness2crying') #self.character.loadAnims({'sleep': 'models/dekinaio/dekinaio-Anim_sleep'}) #self.character.play('sleep') #self.character.loadAnims({'smile': 'models/dekinaio/dekinaio-Anim_smile'}) #self.character.play('smile') #self.character.loadAnims({'surprised': 'models/dekinaio/dekinaio-Anim_surprised'}) #self.character.play('surprised') #anim = self.character.getCurrentAnim() #frames = self.character.getNumFrames(anim) #print anim, frames #self.character.pose(anim, int(frames * 0.9)) # Create smiley's node to indicate 3d points self.smileyActor1 = self.render.attachNewNode('SmileyActorNode1') self.smileyActor2 = self.render.attachNewNode('SmileyActorNode2') smiley = self.loader.loadModel('smiley') smiley.setScale(0.01, 0.01, 0.01) smiley.instanceTo(self.smileyActor1) smiley.instanceTo(self.smileyActor2) n1 = self.character.exposeJoint(None, "modelRoot", "Eyes") n2 = self.character.exposeJoint(None, "modelRoot", "Head") self.label1 = OnscreenText(text='P1', fg=(1, 0, 0, 1), pos=(0, 0), scale=.05, mayChange=1) self.label2 = OnscreenText(text='P2', fg=(1, 0, 0, 1), pos=(0, 0), scale=.05, mayChange=1) self.info1 = OnscreenText(text='dist3d:', fg=(1, 0, 0, 1), pos=(-1, 0), scale=.05, mayChange=1) self.info2 = OnscreenText(text='dist2d:', fg=(1, 0, 0, 1), pos=(-1, -0.1), scale=.05, mayChange=1) self.info3 = OnscreenText(text='camera:', fg=(1, 0, 0, 1), pos=(-1, -0.2), scale=.05, mayChange=1) self.taskMgr.add(self.lookAt, 'lookAt', extraArgs=[n1, n2]) self.taskMgr.add(self.updateNamePos, 'name pos update', extraArgs=[n1, n2]) # These allow you to change cartooning parameters in realtime self.accept("escape", sys.exit, [0]) self.accept("arrow_up", self.camera_f) #self.increaseSeparation) self.accept("arrow_down", self.camera_b) #self.decreaseSeparation) self.accept("arrow_left", self.camera_l) #self.increaseCutoff) self.accept("arrow_right", self.camera_r) #self.decreaseCutoff) self.accept("s", self.saveImage) self.accept("p", self.play) self.accept("o", self.stop) self.accept("n", self.forward) self.accept("b", self.rewind) self.accept("l", self.lookAt) self.accept("h", self.hide) self.accept("1", self.cam_closeup) self.accept("2", self.cam_bustshot) self.accept("3", self.cam_longshot)
def decreaseCutoff(self): self.cutoff = self.cutoff * 0.90000000 print("cutoff: %f" % (self.cutoff)) self.drawnScene.setShaderInput("cutoff", LVecBase4(self.cutoff))
def increaseCutoff(self): self.cutoff = self.cutoff * 1.11111111 print("cutoff: %f" % (self.cutoff)) self.drawnScene.setShaderInput("cutoff", LVecBase4(self.cutoff))
def decreaseSeparation(self): self.separation = self.separation * 0.90000000 print("separation: %f" % (self.separation)) self.drawnScene.setShaderInput( "separation", LVecBase4(self.separation, 0, self.separation, 0))
def __init__(self): self.base = ShowBase() #wp = WindowProperties() #wp.setSize(640, 480) #self.base.win.requestProperties(wp) self.base.camera.setPos(0, 0, 0) self.base.camLens.setNearFar(0.01, 1000.0) self.base.camLens.setFov(50) self.base.setBackgroundColor(1, 1, 1) if not self.base.win.getGsg().getSupportsBasicShaders(): print( "Toon Shader: Video driver reports that Cg shaders are not supported." ) return tempnode = NodePath(PandaNode("temp node")) tempnode.setShader( self.base.loader.loadShader("shader/lightingGen.sha")) self.base.cam.node().setInitialState(tempnode.getState()) light = self.base.render.attachNewNode("light") light.setPos(30, -50, 0) self.base.render.setShaderInput("light", light) normalsBuffer = self.base.win.makeTextureBuffer("normalsBuffer", 0, 0) normalsBuffer.setClearColor(LVecBase4(0.5, 0.5, 0.5, 1)) self.normalsBuffer = normalsBuffer normalsCamera = self.base.makeCamera( normalsBuffer, lens=self.base.cam.node().getLens()) normalsCamera.node().setScene(self.base.render) tempnode = NodePath(PandaNode("temp node")) tempnode.setShader(self.base.loader.loadShader("shader/normalGen.sha")) normalsCamera.node().setInitialState(tempnode.getState()) drawnScene = normalsBuffer.getTextureCard() drawnScene.setTransparency(1) drawnScene.setColor(1, 1, 1, 0) drawnScene.reparentTo(self.base.render2d) #self.base.drawnScene = drawnScene self.separation = 0.00065 self.cutoff = 0.3 inkGen = self.base.loader.loadShader("shader/inkGen.sha") drawnScene.setShader(inkGen) drawnScene.setShaderInput( "separation", LVecBase4(self.separation, 0, self.separation, 0)) drawnScene.setShaderInput("cutoff", LVecBase4(self.cutoff)) # Load a model #self.smiley = self.loader.loadModel('smiley') #self.smiley.reparentTo(self.render) #self.smiley.setPos(0, 10.0, 0) self.actors = [Actor(), Actor(), Actor(), Actor()] self.actors[0].loadModel('models/dekiruo/dekiruo') self.actors[0].reparentTo(self.base.render) self.actors[0].loadAnims( {'normal': 'models/dekiruo/dekiruo-Anim_normal'}) self.actors[0].loadAnims( {'anger': 'models/dekiruo/dekiruo-Anim_anger'}) self.actors[0].loadAnims( {'sadness2crying': 'models/dekiruo/dekiruo-Anim_sadness2crying'}) self.actors[0].loadAnims( {'sleep': 'models/dekiruo/dekiruo-Anim_sleep'}) self.actors[0].loadAnims( {'smile': 'models/dekiruo/dekiruo-Anim_smile'}) self.actors[0].loadAnims( {'surprised': 'models/dekiruo/dekiruo-Anim_surprised'}) for i in range(1, len(self.actors)): self.actors[i].loadModel('models/dekinaio/dekinaio') self.actors[i].reparentTo(self.base.render) self.actors[i].loadAnims( {'normal': 'models/dekinaio/dekinaio-Anim_normal'}) self.actors[i].loadAnims( {'anger': 'models/dekinaio/dekinaio-Anim_anger'}) self.actors[i].loadAnims({ 'sadness2crying': 'models/dekinaio/dekinaio-Anim_sadness2crying' }) self.actors[i].loadAnims( {'sleep': 'models/dekinaio/dekinaio-Anim_sleep'}) self.actors[i].loadAnims( {'smile': 'models/dekinaio/dekinaio-Anim_smile'}) self.actors[i].loadAnims( {'surprised': 'models/dekinaio/dekinaio-Anim_surprised'}) self.info = None # frame集合体(page)のxml self.actors_dict = {} # 名前付けされた役者
def reconfigure(self, fullrebuild, changed): configuration = self.configuration if fullrebuild: self.cleanup() if len(configuration) == 0: return auxbits = 0 needtex = set(['color']) needtexcoord = set(['color']) if 'CartoonInk' in configuration: needtex.add('aux') auxbits |= AuxBitplaneAttrib.ABOAuxNormal needtexcoord.add('aux') if 'AmbientOcclusion' in configuration: needtex.add('depth') needtex.add('ssao0') needtex.add('ssao1') needtex.add('ssao2') needtex.add('aux') auxbits |= AuxBitplaneAttrib.ABOAuxNormal needtexcoord.add('ssao2') if 'BlurSharpen' in configuration: needtex.add('blur0') needtex.add('blur1') needtexcoord.add('blur1') if 'Bloom' in configuration: needtex.add('bloom0') needtex.add('bloom1') needtex.add('bloom2') needtex.add('bloom3') auxbits |= AuxBitplaneAttrib.ABOGlow needtexcoord.add('bloom3') if 'ViewGlow' in configuration: auxbits |= AuxBitplaneAttrib.ABOGlow if 'VolumetricLighting' in configuration: needtex.add(configuration['VolumetricLighting'].source) for tex in needtex: self.textures[tex] = Texture('scene-' + tex) self.textures[tex].setWrapU(Texture.WMClamp) self.textures[tex].setWrapV(Texture.WMClamp) self.finalQuad = self.manager.renderSceneInto( textures=self.textures, auxbits=auxbits) if self.finalQuad == None: self.cleanup() return False if 'BlurSharpen' in configuration: blur0 = self.textures['blur0'] blur1 = self.textures['blur1'] self.blur.append( self.manager.renderQuadInto(colortex=blur0, div=2)) self.blur.append(self.manager.renderQuadInto(colortex=blur1)) self.blur[0].setShaderInput('src', self.textures['color']) self.blur[0].setShader(self.loadShader('filter-blurx.sha')) self.blur[1].setShaderInput('src', blur0) self.blur[1].setShader(self.loadShader('filter-blury.sha')) if 'AmbientOcclusion' in configuration: ssao0 = self.textures['ssao0'] ssao1 = self.textures['ssao1'] ssao2 = self.textures['ssao2'] self.ssao.append(self.manager.renderQuadInto(colortex=ssao0)) self.ssao.append( self.manager.renderQuadInto(colortex=ssao1, div=2)) self.ssao.append(self.manager.renderQuadInto(colortex=ssao2)) self.ssao[0].setShaderInput('depth', self.textures['depth']) self.ssao[0].setShaderInput('normal', self.textures['aux']) self.ssao[0].setShaderInput( 'random', loader.loadTexture('maps/random.rgb')) self.ssao[0].setShader( Shader.make( SSAO_BODY % configuration['AmbientOcclusion'].numsamples, Shader.SL_Cg)) self.ssao[1].setShaderInput('src', ssao0) self.ssao[1].setShader(self.loadShader('filter-blurx.sha')) self.ssao[2].setShaderInput('src', ssao1) self.ssao[2].setShader(self.loadShader('filter-blury.sha')) if 'Bloom' in configuration: bloomconf = configuration['Bloom'] bloom0 = self.textures['bloom0'] bloom1 = self.textures['bloom1'] bloom2 = self.textures['bloom2'] bloom3 = self.textures['bloom3'] if bloomconf.size == 'large': scale = 8 downsampler = 'filter-down4.sha' else: if bloomconf.size == 'medium': scale = 4 downsampler = 'filter-copy.sha' else: scale = 2 downsampler = 'filter-copy.sha' self.bloom.append( self.manager.renderQuadInto(colortex=bloom0, div=2, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom1, div=scale, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom2, div=scale, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom3, div=scale, align=scale)) self.bloom[0].setShaderInput('src', self.textures['color']) self.bloom[0].setShader(self.loadShader('filter-bloomi.sha')) self.bloom[1].setShaderInput('src', bloom0) self.bloom[1].setShader(self.loadShader(downsampler)) self.bloom[2].setShaderInput('src', bloom1) self.bloom[2].setShader(self.loadShader('filter-bloomx.sha')) self.bloom[3].setShaderInput('src', bloom2) self.bloom[3].setShader(self.loadShader('filter-bloomy.sha')) texcoords = {} texcoordPadding = {} for tex in needtexcoord: if self.textures[tex].getAutoTextureScale( ) != ATSNone or 'HalfPixelShift' in configuration: texcoords[tex] = 'l_texcoord_' + tex texcoordPadding['l_texcoord_' + tex] = tex else: texcoords[tex] = 'l_texcoord' texcoordPadding['l_texcoord'] = None texcoordSets = list(enumerate(texcoordPadding.keys())) text = '//Cg\n' text += 'void vshader(float4 vtx_position : POSITION,\n' text += ' out float4 l_position : POSITION,\n' for texcoord, padTex in texcoordPadding.items(): if padTex is not None: text += ' uniform float4 texpad_tx%s,\n' % padTex if 'HalfPixelShift' in configuration: text += ' uniform float4 texpix_tx%s,\n' % padTex for i, name in texcoordSets: text += ' out float2 %s : TEXCOORD%d,\n' % (name, i) text += ' uniform float4x4 mat_modelproj)\n' text += '{\n' text += ' l_position = mul(mat_modelproj, vtx_position);\n' for texcoord, padTex in texcoordPadding.items(): if padTex is None: text += ' %s = vtx_position.xz * float2(0.5, 0.5) + float2(0.5, 0.5);\n' % texcoord else: text += ' %s = (vtx_position.xz * texpad_tx%s.xy) + texpad_tx%s.xy;\n' % ( texcoord, padTex, padTex) if 'HalfPixelShift' in configuration: text += ' %s += texpix_tx%s.xy * 0.5;\n' % (texcoord, padTex) text += '}\n' text += 'void fshader(\n' for i, name in texcoordSets: text += ' float2 %s : TEXCOORD%d,\n' % (name, i) for key in self.textures: text += ' uniform sampler2D k_tx' + key + ',\n' if 'CartoonInk' in configuration: text += ' uniform float4 k_cartoonseparation,\n' text += ' uniform float4 k_cartooncolor,\n' text += ' uniform float4 texpix_txaux,\n' if 'BlurSharpen' in configuration: text += ' uniform float4 k_blurval,\n' if 'VolumetricLighting' in configuration: text += ' uniform float4 k_casterpos,\n' text += ' uniform float4 k_vlparams,\n' text += ' out float4 o_color : COLOR)\n' text += '{\n' text += ' o_color = tex2D(k_txcolor, %s);\n' % texcoords['color'] if 'CartoonInk' in configuration: text += CARTOON_BODY % {'texcoord': texcoords['aux']} if 'AmbientOcclusion' in configuration: text += ' o_color *= tex2D(k_txssao2, %s).r;\n' % texcoords[ 'ssao2'] if 'BlurSharpen' in configuration: text += ' o_color = lerp(tex2D(k_txblur1, %s), o_color, k_blurval.x);\n' % texcoords[ 'blur1'] if 'Bloom' in configuration: text += ' o_color = saturate(o_color);\n' text += ' float4 bloom = 0.5 * tex2D(k_txbloom3, %s);\n' % texcoords[ 'bloom3'] text += ' o_color = 1-((1-bloom)*(1-o_color));\n' if 'ViewGlow' in configuration: text += ' o_color.r = o_color.a;\n' if 'VolumetricLighting' in configuration: text += ' float decay = 1.0f;\n' text += ' float2 curcoord = %s;\n' % texcoords['color'] text += ' float2 lightdir = curcoord - k_casterpos.xy;\n' text += ' lightdir *= k_vlparams.x;\n' text += ' half4 sample = tex2D(k_txcolor, curcoord);\n' text += ' float3 vlcolor = sample.rgb * sample.a;\n' text += ' for (int i = 0; i < %s; i++) {\n' % int( configuration['VolumetricLighting'].numsamples) text += ' curcoord -= lightdir;\n' text += ' sample = tex2D(k_tx%s, curcoord);\n' % configuration[ 'VolumetricLighting'].source text += ' sample *= sample.a * decay;//*weight\n' text += ' vlcolor += sample.rgb;\n' text += ' decay *= k_vlparams.y;\n' text += ' }\n' text += ' o_color += float4(vlcolor * k_vlparams.z, 1);\n' if 'GammaAdjust' in configuration: gamma = configuration['GammaAdjust'] if gamma == 0.5: text += ' o_color.rgb = sqrt(o_color.rgb);\n' elif gamma == 2.0: text += ' o_color.rgb *= o_color.rgb;\n' elif gamma != 1.0: text += ' o_color.rgb = pow(o_color.rgb, %ff);\n' % gamma if 'Inverted' in configuration: text += ' o_color = float4(1, 1, 1, 1) - o_color;\n' text += '}\n' self.finalQuad.setShader(Shader.make(text, Shader.SL_Cg)) for tex in self.textures: self.finalQuad.setShaderInput('tx' + tex, self.textures[tex]) self.task = taskMgr.add(self.update, 'common-filters-update') if changed == 'CartoonInk' or fullrebuild: if 'CartoonInk' in configuration: c = configuration['CartoonInk'] self.finalQuad.setShaderInput( 'cartoonseparation', LVecBase4(c.separation, 0, c.separation, 0)) self.finalQuad.setShaderInput('cartooncolor', c.color) if changed == 'BlurSharpen' or fullrebuild: if 'BlurSharpen' in configuration: blurval = configuration['BlurSharpen'] self.finalQuad.setShaderInput( 'blurval', LVecBase4(blurval, blurval, blurval, blurval)) if changed == 'Bloom' or fullrebuild: if 'Bloom' in configuration: bloomconf = configuration['Bloom'] intensity = bloomconf.intensity * 3.0 self.bloom[0].setShaderInput('blend', bloomconf.blendx, bloomconf.blendy, bloomconf.blendz, bloomconf.blendw * 2.0) self.bloom[0].setShaderInput( 'trigger', bloomconf.mintrigger, 1.0 / (bloomconf.maxtrigger - bloomconf.mintrigger), 0.0, 0.0) self.bloom[0].setShaderInput('desat', bloomconf.desat) self.bloom[3].setShaderInput('intensity', intensity, intensity, intensity, intensity) if changed == 'VolumetricLighting' or fullrebuild: if 'VolumetricLighting' in configuration: config = configuration['VolumetricLighting'] tcparam = config.density / float(config.numsamples) self.finalQuad.setShaderInput('vlparams', tcparam, config.decay, config.exposure, 0.0) if changed == 'AmbientOcclusion' or fullrebuild: if 'AmbientOcclusion' in configuration: config = configuration['AmbientOcclusion'] self.ssao[0].setShaderInput( 'params1', config.numsamples, -float(config.amount) / config.numsamples, config.radius, 0) self.ssao[0].setShaderInput('params2', config.strength, config.falloff, 0, 0) self.update() return True
def add_shadders(self: ShowBase): normalsBuffer = self.win.makeTextureBuffer("normalsBuffer", 0, 0) normalsBuffer.setClearColor(LVecBase4(0.5, 0.5, 0.5, 0.5)) self.normalsBuffer = normalsBuffer normalsCamera = self.makeCamera(normalsBuffer, lens=self.cam.node().getLens()) normalsCamera.node().setScene(self.render) tempnode = NodePath(PandaNode("temp node")) normalGen = self.loader.loadShader("app/view/shaders/normalGen.sha") tempnode.setShader(normalGen) tempnode.setShaderInput("showborders", LVecBase4(1)) normalsCamera.node().setInitialState(tempnode.getState()) depth_buffer = self.win.makeTextureBuffer("depthBuffer", 0, 0) depth_buffer.setClearColor(LVecBase4(0, 0, 0, 0)) self.depth_buffer = depth_buffer depth_camera = self.makeCamera(depth_buffer, lens=self.cam.node().getLens()) depth_camera.node().setScene(self.render) tempnode = NodePath(PandaNode("temp node depth")) depth_gen = self.loader.loadShader("app/view/shaders/depthGen.sha") tempnode.setShader(depth_gen) depth_camera.node().setInitialState(tempnode.getState()) colors_buffer = self.win.makeTextureBuffer("colorsBuffer", 0, 0) colors_buffer.setClearColor(LVecBase4(0, 0, 0, 0)) self.colors_buffer = colors_buffer colorsCamera = self.makeCamera(colors_buffer, lens=self.cam.node().getLens()) colorsCamera.node().setScene(self.render) tempnode = NodePath(PandaNode("temp node colors")) colorGen = self.loader.loadShader("app/view/shaders/colorGen.sha") tempnode.setShader(colorGen) tempnode.setShaderInput("showborders", LVecBase4(1)) tempnode.setShaderInput("colorborders", LVecBase4(0, 0, 0, 1)) colorsCamera.node().setInitialState(tempnode.getState()) # what we actually do to put edges on screen is apply them as a texture to # a transparent screen-fitted card drawnScene = normalsBuffer.getTextureCard() colorBorderTex = colors_buffer.getTextureCard() depthTex = depth_buffer.getTextureCard() drawnScene.setTransparency(1) drawnScene.setColor(1, 1, 1, 1) drawnScene.reparentTo(render2d) self.drawnScene = drawnScene # this shader accepts, as input, the picture from the normals buffer. # it compares each adjacent pixel, looking for discontinuities. # wherever a discontinuity exists, it emits black ink. self.separation = 0.0005 self.separation = 1 self.cutoff = 0.3 inkGen = loader.loadShader("app/view/shaders/inkGen.sha") stage_border = TextureStage("border") stage_border.setSort(1) drawnScene.setTexture(stage_border, colorBorderTex.getTexture()) stage_depth = TextureStage("depth") stage_depth.setSort(2) drawnScene.setTexture(stage_depth, depthTex.getTexture()) drawnScene.setShader(inkGen) drawnScene.setShaderInput( "separation", LVecBase4(self.separation, 0, self.separation, 0)) drawnScene.setShaderInput("screen", 1280, 720) drawnScene.setShaderInput("cutoff", LVecBase4(self.cutoff)) print("SHADER DEBUG") print(drawnScene.findAllTextureStages())
def reconfigure(self, fullrebuild, changed): """ Reconfigure is called whenever any configuration change is made. """ configuration = self.configuration if fullrebuild: self.cleanup() if len(configuration) == 0: return if not self.manager.win.gsg.getSupportsBasicShaders(): return False auxbits = 0 needtex = set(["color"]) needtexcoord = set(["color"]) if "CartoonInk" in configuration: needtex.add("aux") auxbits |= AuxBitplaneAttrib.ABOAuxNormal needtexcoord.add("aux") if "AmbientOcclusion" in configuration: needtex.add("depth") needtex.add("ssao0") needtex.add("ssao1") needtex.add("ssao2") needtex.add("aux") auxbits |= AuxBitplaneAttrib.ABOAuxNormal needtexcoord.add("ssao2") if "BlurSharpen" in configuration: needtex.add("blur0") needtex.add("blur1") needtexcoord.add("blur1") if "Bloom" in configuration: needtex.add("bloom0") needtex.add("bloom1") needtex.add("bloom2") needtex.add("bloom3") auxbits |= AuxBitplaneAttrib.ABOGlow needtexcoord.add("bloom3") if "ViewGlow" in configuration: auxbits |= AuxBitplaneAttrib.ABOGlow if "VolumetricLighting" in configuration: needtex.add(configuration["VolumetricLighting"].source) for tex in needtex: self.textures[tex] = Texture("scene-" + tex) self.textures[tex].setWrapU(Texture.WMClamp) self.textures[tex].setWrapV(Texture.WMClamp) fbprops = None clamping = None if "HighDynamicRange" in configuration: fbprops = FrameBufferProperties() fbprops.setFloatColor(True) fbprops.setSrgbColor(False) clamping = False self.finalQuad = self.manager.renderSceneInto( textures=self.textures, auxbits=auxbits, fbprops=fbprops, clamping=clamping) if self.finalQuad is None: self.cleanup() return False if "BlurSharpen" in configuration: blur0 = self.textures["blur0"] blur1 = self.textures["blur1"] self.blur.append( self.manager.renderQuadInto("filter-blur0", colortex=blur0, div=2)) self.blur.append( self.manager.renderQuadInto("filter-blur1", colortex=blur1)) self.blur[0].setShaderInput("src", self.textures["color"]) self.blur[0].setShader(Shader.make(BLUR_X, Shader.SL_Cg)) self.blur[1].setShaderInput("src", blur0) self.blur[1].setShader(Shader.make(BLUR_Y, Shader.SL_Cg)) if "AmbientOcclusion" in configuration: ssao0 = self.textures["ssao0"] ssao1 = self.textures["ssao1"] ssao2 = self.textures["ssao2"] self.ssao.append( self.manager.renderQuadInto("filter-ssao0", colortex=ssao0)) self.ssao.append( self.manager.renderQuadInto("filter-ssao1", colortex=ssao1, div=2)) self.ssao.append( self.manager.renderQuadInto("filter-ssao2", colortex=ssao2)) self.ssao[0].setShaderInput("depth", self.textures["depth"]) self.ssao[0].setShaderInput("normal", self.textures["aux"]) self.ssao[0].setShaderInput( "random", base.loader.loadTexture("maps/random.rgb")) self.ssao[0].setShader( Shader.make( SSAO_BODY % configuration["AmbientOcclusion"].numsamples, Shader.SL_Cg)) self.ssao[1].setShaderInput("src", ssao0) self.ssao[1].setShader(Shader.make(BLUR_X, Shader.SL_Cg)) self.ssao[2].setShaderInput("src", ssao1) self.ssao[2].setShader(Shader.make(BLUR_Y, Shader.SL_Cg)) if "Bloom" in configuration: bloomconf = configuration["Bloom"] bloom0 = self.textures["bloom0"] bloom1 = self.textures["bloom1"] bloom2 = self.textures["bloom2"] bloom3 = self.textures["bloom3"] if bloomconf.size == "large": scale = 8 downsamplerName = "filter-down4" downsampler = DOWN_4 elif bloomconf.size == "medium": scale = 4 downsamplerName = "filter-copy" downsampler = COPY else: scale = 2 downsamplerName = "filter-copy" downsampler = COPY self.bloom.append( self.manager.renderQuadInto("filter-bloomi", colortex=bloom0, div=2, align=scale)) self.bloom.append( self.manager.renderQuadInto(downsamplerName, colortex=bloom1, div=scale, align=scale)) self.bloom.append( self.manager.renderQuadInto("filter-bloomx", colortex=bloom2, div=scale, align=scale)) self.bloom.append( self.manager.renderQuadInto("filter-bloomy", colortex=bloom3, div=scale, align=scale)) self.bloom[0].setShaderInput("src", self.textures["color"]) self.bloom[0].setShader(Shader.make(BLOOM_I, Shader.SL_Cg)) self.bloom[1].setShaderInput("src", bloom0) self.bloom[1].setShader(Shader.make(downsampler, Shader.SL_Cg)) self.bloom[2].setShaderInput("src", bloom1) self.bloom[2].setShader(Shader.make(BLOOM_X, Shader.SL_Cg)) self.bloom[3].setShaderInput("src", bloom2) self.bloom[3].setShader(Shader.make(BLOOM_Y, Shader.SL_Cg)) texcoords = {} texcoordPadding = {} for tex in needtexcoord: if self.textures[tex].getAutoTextureScale() != ATSNone or \ "HalfPixelShift" in configuration: texcoords[tex] = "l_texcoord_" + tex texcoordPadding["l_texcoord_" + tex] = tex else: # Share unpadded texture coordinates. texcoords[tex] = "l_texcoord" texcoordPadding["l_texcoord"] = None texcoordSets = list(enumerate(texcoordPadding.keys())) text = "//Cg\n" if "HighDynamicRange" in configuration: text += "static const float3x3 aces_input_mat = {\n" text += " {0.59719, 0.35458, 0.04823},\n" text += " {0.07600, 0.90834, 0.01566},\n" text += " {0.02840, 0.13383, 0.83777},\n" text += "};\n" text += "static const float3x3 aces_output_mat = {\n" text += " { 1.60475, -0.53108, -0.07367},\n" text += " {-0.10208, 1.10813, -0.00605},\n" text += " {-0.00327, -0.07276, 1.07602},\n" text += "};\n" text += "void vshader(float4 vtx_position : POSITION,\n" text += " out float4 l_position : POSITION,\n" for texcoord, padTex in texcoordPadding.items(): if padTex is not None: text += " uniform float4 texpad_tx%s,\n" % (padTex) if "HalfPixelShift" in configuration: text += " uniform float4 texpix_tx%s,\n" % (padTex) for i, name in texcoordSets: text += " out float2 %s : TEXCOORD%d,\n" % (name, i) text += " uniform float4x4 mat_modelproj)\n" text += "{\n" text += " l_position = mul(mat_modelproj, vtx_position);\n" for texcoord, padTex in texcoordPadding.items(): if padTex is None: text += " %s = vtx_position.xz * float2(0.5, 0.5) + float2(0.5, 0.5);\n" % ( texcoord) else: text += " %s = (vtx_position.xz * texpad_tx%s.xy) + texpad_tx%s.xy;\n" % ( texcoord, padTex, padTex) if "HalfPixelShift" in configuration: text += " %s += texpix_tx%s.xy * 0.5;\n" % (texcoord, padTex) text += "}\n" text += "void fshader(\n" for i, name in texcoordSets: text += " float2 %s : TEXCOORD%d,\n" % (name, i) for key in self.textures: text += " uniform sampler2D k_tx" + key + ",\n" if "CartoonInk" in configuration: text += " uniform float4 k_cartoonseparation,\n" text += " uniform float4 k_cartooncolor,\n" text += " uniform float4 texpix_txaux,\n" if "BlurSharpen" in configuration: text += " uniform float4 k_blurval,\n" if "VolumetricLighting" in configuration: text += " uniform float4 k_casterpos,\n" text += " uniform float4 k_vlparams,\n" if "ExposureAdjust" in configuration: text += " uniform float k_exposure,\n" text += " out float4 o_color : COLOR)\n" text += "{\n" text += " o_color = tex2D(k_txcolor, %s);\n" % ( texcoords["color"]) if "CartoonInk" in configuration: text += CARTOON_BODY % {"texcoord": texcoords["aux"]} if "AmbientOcclusion" in configuration: text += " o_color *= tex2D(k_txssao2, %s).r;\n" % ( texcoords["ssao2"]) if "BlurSharpen" in configuration: text += " o_color = lerp(tex2D(k_txblur1, %s), o_color, k_blurval.x);\n" % ( texcoords["blur1"]) if "Bloom" in configuration: text += " o_color = saturate(o_color);\n" text += " float4 bloom = 0.5 * tex2D(k_txbloom3, %s);\n" % ( texcoords["bloom3"]) text += " o_color = 1-((1-bloom)*(1-o_color));\n" if "ViewGlow" in configuration: text += " o_color.r = o_color.a;\n" if "VolumetricLighting" in configuration: text += " float decay = 1.0f;\n" text += " float2 curcoord = %s;\n" % (texcoords["color"]) text += " float2 lightdir = curcoord - k_casterpos.xy;\n" text += " lightdir *= k_vlparams.x;\n" text += " half4 sample = tex2D(k_txcolor, curcoord);\n" text += " float3 vlcolor = sample.rgb * sample.a;\n" text += " for (int i = 0; i < %s; i++) {\n" % (int( configuration["VolumetricLighting"].numsamples)) text += " curcoord -= lightdir;\n" text += " sample = tex2D(k_tx%s, curcoord);\n" % ( configuration["VolumetricLighting"].source) text += " sample *= sample.a * decay;//*weight\n" text += " vlcolor += sample.rgb;\n" text += " decay *= k_vlparams.y;\n" text += " }\n" text += " o_color += float4(vlcolor * k_vlparams.z, 1);\n" if "ExposureAdjust" in configuration: text += " o_color.rgb *= k_exposure;\n" # With thanks to Stephen Hill! if "HighDynamicRange" in configuration: text += " float3 aces_color = mul(aces_input_mat, o_color.rgb);\n" text += " o_color.rgb = saturate(mul(aces_output_mat, (aces_color * (aces_color + 0.0245786f) - 0.000090537f) / (aces_color * (0.983729f * aces_color + 0.4329510f) + 0.238081f)));\n" if "GammaAdjust" in configuration: gamma = configuration["GammaAdjust"] if gamma == 0.5: text += " o_color.rgb = sqrt(o_color.rgb);\n" elif gamma == 2.0: text += " o_color.rgb *= o_color.rgb;\n" elif gamma != 1.0: text += " o_color.rgb = pow(o_color.rgb, %ff);\n" % ( gamma) if "SrgbEncode" in configuration: text += " o_color.r = (o_color.r < 0.0031308) ? (o_color.r * 12.92) : (1.055 * pow(o_color.r, 0.41666) - 0.055);\n" text += " o_color.g = (o_color.g < 0.0031308) ? (o_color.g * 12.92) : (1.055 * pow(o_color.g, 0.41666) - 0.055);\n" text += " o_color.b = (o_color.b < 0.0031308) ? (o_color.b * 12.92) : (1.055 * pow(o_color.b, 0.41666) - 0.055);\n" if "Inverted" in configuration: text += " o_color = float4(1, 1, 1, 1) - o_color;\n" text += "}\n" shader = Shader.make(text, Shader.SL_Cg) if not shader: return False self.finalQuad.setShader(shader) for tex in self.textures: self.finalQuad.setShaderInput("tx" + tex, self.textures[tex]) self.task = taskMgr.add(self.update, "common-filters-update") if changed == "CartoonInk" or fullrebuild: if "CartoonInk" in configuration: c = configuration["CartoonInk"] self.finalQuad.setShaderInput( "cartoonseparation", LVecBase4(c.separation, 0, c.separation, 0)) self.finalQuad.setShaderInput("cartooncolor", c.color) if changed == "BlurSharpen" or fullrebuild: if "BlurSharpen" in configuration: blurval = configuration["BlurSharpen"] self.finalQuad.setShaderInput( "blurval", LVecBase4(blurval, blurval, blurval, blurval)) if changed == "Bloom" or fullrebuild: if "Bloom" in configuration: bloomconf = configuration["Bloom"] intensity = bloomconf.intensity * 3.0 self.bloom[0].setShaderInput("blend", bloomconf.blendx, bloomconf.blendy, bloomconf.blendz, bloomconf.blendw * 2.0) self.bloom[0].setShaderInput( "trigger", bloomconf.mintrigger, 1.0 / (bloomconf.maxtrigger - bloomconf.mintrigger), 0.0, 0.0) self.bloom[0].setShaderInput("desat", bloomconf.desat) self.bloom[3].setShaderInput("intensity", intensity, intensity, intensity, intensity) if changed == "VolumetricLighting" or fullrebuild: if "VolumetricLighting" in configuration: config = configuration["VolumetricLighting"] tcparam = config.density / float(config.numsamples) self.finalQuad.setShaderInput("vlparams", tcparam, config.decay, config.exposure, 0.0) if changed == "AmbientOcclusion" or fullrebuild: if "AmbientOcclusion" in configuration: config = configuration["AmbientOcclusion"] self.ssao[0].setShaderInput( "params1", config.numsamples, -float(config.amount) / config.numsamples, config.radius, 0) self.ssao[0].setShaderInput("params2", config.strength, config.falloff, 0, 0) if changed == "ExposureAdjust" or fullrebuild: if "ExposureAdjust" in configuration: stops = configuration["ExposureAdjust"] self.finalQuad.setShaderInput("exposure", 2**stops) self.update() return True
def __init__(self, panda3d): # Inicialización de variables self.winsize = [0, 0] self.panda3d = panda3d self.panda3d.mouse_on_workspace = False # Desabilita el comportamiento por defecto de la camara self.panda3d.disable_mouse() # Llama a la función self.window_rezise_event cuando la ventana cambia de tamaño self.accept('window-event', self.window_rezise_event) # self.panda3d.accept('aspectRatioChanged', lambda: print("ss")) # Creamos el punto donde se centrará la cámara target_pos = Point3(0., 0., 0.) self.panda3d.cam_target = self.panda3d.render.attach_new_node("camera_target") self.panda3d.cam_target.set_pos(target_pos) self.panda3d.camera.reparent_to(self.panda3d.cam_target) self.panda3d.camera.set_y(-50.) # Definimos la cambinación de teclas para el control de la camara self.camera_active = False self.orbit_mouse_btn = "mouse2" self.orbit_keyboard_btn = "shift" self.orbit_mouse_reference = None self.orbit_camera_reference = None self.pan_mouse_btn = "mouse2" self.pan_keyboard_btn = "mouse2" self.pan_mouse_reference = None self.pan_camera_reference = None self.zoom_mouse_btn = "mouse2" self.zoom_keyboard_btn = "control" self.zoom_mouse_reference = None self.zoom_camera_reference = None # Establecemos los valores máximos y minimos para el zoom self.max_zoom = 10 self.min_zoom = 0.1 # Creamos la tarea de control de la camara self.panda3d.task_mgr.add(self.camera_control_task, "camera_control") # El movimiento de la rueda del mouse controla el zoom self.panda3d.accept("wheel_up", self.zoom_in) self.panda3d.accept("wheel_down", self.zoom_out) # Una fución de prueba para comprobar la posición del mouse en el modelo 3d # self.panda3d.accept("mouse1", self.entity_select) # Se establece la lente ortografica en lugar de la perspectiva self.lens_type = "OrthographicLens" self.set_lens(self.lens_type) # Agrega un indicador de ejes en la esquina inferior izquierda self.corner = self.panda3d.camera.attachNewNode("corner of screen") # self.axis = self.panda3d.loader.loadModel("data/geom/custom-axis") # self.axis = self.panda3d.loader.loadModel("data/geom/view_gizmo_F") self.view_gizmo = list() self.view_gizmo.append(self.panda3d.loader.loadModel("data/geom/view_gizmo_compass")) # self.view_gizmo.append(self.panda3d.loader.loadModel("data/geom/view_gizmo_L")) # self.view_cube = ViewGizmoZone() # self.view_cube.set_geom(self.axis) for gizmo_geom in self.view_gizmo: gizmo_geom.setLightOff(1) # gizmo_geom.setColorScale(1,1,1,1) gizmo_geom.setShaderInput("colorborders", LVecBase4(0, 0, 0, 0.25)) gizmo = ViewGizmoZone() gizmo.set_geom(gizmo_geom) gizmo_geom.node().setBounds(BoundingSphere(Point3(0, 0, 0), 10)) gizmo_geom.node().setFinal(True) #gizmo_geom.showTightBounds() # gizmo_geom.showBounds() self.show_view_gizmo() # Agregamos una luz puntual en la ubicación de la camara plight = DirectionalLight("camera_light") plight.setColor((1, 1, 1, 1)) #plight.setAttenuation((1, 0, 0)) #print("getMaxDistance {}".format(plight.getMaxDistance())) self.panda3d.plight_node = self.panda3d.render.attach_new_node(plight) self.panda3d.plight_node.setPos(0, -50, 0) self.panda3d.render.setLight(self.panda3d.plight_node) self.panda3d.plight_node.reparentTo(self.panda3d.camera) # Agregamos luz ambiental que disminuya las zonas oscuras alight = AmbientLight('alight') alight.setColor((0.3, 0.3, 0.3, 1)) alnp = self.panda3d.render.attachNewNode(alight) self.panda3d.render.setLight(alnp) #def init_select_detection(self): self.traverser = CollisionTraverser("") # self.traverser.show_collisions(self.panda3d.render) self.picker_ray = CollisionRay() self.handler = CollisionHandlerQueue() self.picker_node = CollisionNode('mouseRay') self.picker_np = self.panda3d.camera.attachNewNode(self.picker_node) self.picker_node.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.picker_ray = CollisionRay() self.picker_node.addSolid(self.picker_ray) self.traverser.addCollider(self.picker_np, self.handler)
def reconfigure(self, fullrebuild, changed): """ Reconfigure is called whenever any configuration change is made. """ configuration = self.configuration if (fullrebuild): self.cleanup() if (len(configuration) == 0): return if not self.manager.win.gsg.getSupportsBasicShaders(): return False auxbits = 0 # Color texture is already created at init, # we don't need to make it. needtex = set() needtexcoord = set(["color"]) if ("CartoonInk" in configuration): needtex.add("aux") auxbits |= AuxBitplaneAttrib.ABOAuxNormal needtexcoord.add("aux") if ("AmbientOcclusion" in configuration): needtex.add("depth") needtex.add("ssao0") needtex.add("ssao1") needtex.add("ssao2") needtex.add("aux") auxbits |= AuxBitplaneAttrib.ABOAuxNormal needtexcoord.add("ssao2") if ("BlurSharpen" in configuration or "DOF" in configuration): needtex.add("blur0") needtex.add("blur1") needtexcoord.add("blur1") if ("DOF" in configuration): needtex.add("depth") if ("FXAA" in configuration): needtex.add("fxaa") if ("Bloom" in configuration): needtex.add("bloom0") needtex.add("bloom1") needtex.add("bloom2") needtex.add("bloom3") auxbits |= AuxBitplaneAttrib.ABOGlow needtexcoord.add("bloom3") if ("ViewGlow" in configuration): auxbits |= AuxBitplaneAttrib.ABOGlow if ("VolumetricLighting" in configuration): needtex.add(configuration["VolumetricLighting"].source) for tex in needtex: self.makeTexture(tex) self.finalQuad = self.manager.renderSceneInto( textures=self.textures, auxbits=auxbits) if (self.finalQuad == None): self.cleanup() return False if ("FXAA" in configuration): fxaa = self.textures["fxaa"] self.fxaa = self.manager.renderQuadInto(colortex=fxaa) self.fxaa.setShader( Shader.load(Shader.SL_GLSL, "phase_14/models/shaders/fxaa.vert.glsl", "phase_14/models/shaders/fxaa.frag.glsl")) self.fxaa.setShaderInput("sceneTexture", self.textures["color"]) if ("BlurSharpen" in configuration or "DOF" in configuration): blur0 = self.textures["blur0"] blur1 = self.textures["blur1"] self.blur.append( self.manager.renderQuadInto(colortex=blur0, div=2)) self.blur.append(self.manager.renderQuadInto(colortex=blur1)) self.blur[0].setShaderInput("src", self.textures["color"]) self.blur[0].setShader( self.loadShader("phase_3/models/shaders/filter-blurx.sha")) self.blur[1].setShaderInput("src", blur0) self.blur[1].setShader( self.loadShader("phase_3/models/shaders/filter-blury.sha")) if ("AmbientOcclusion" in configuration): ssao0 = self.textures["ssao0"] ssao1 = self.textures["ssao1"] ssao2 = self.textures["ssao2"] self.ssao.append(self.manager.renderQuadInto(colortex=ssao0)) self.ssao.append( self.manager.renderQuadInto(colortex=ssao1, div=2)) self.ssao.append(self.manager.renderQuadInto(colortex=ssao2)) self.ssao[0].setShaderInput("depth", self.textures["depth"]) self.ssao[0].setShaderInput("normal", self.textures["aux"]) self.ssao[0].setShaderInput( "random", loader.loadTexture("maps/random.rgb")) self.ssao[0].setShader(Shader.make(SSAO_BODY, Shader.SL_Cg)) self.ssao[1].setShaderInput("src", ssao0) self.ssao[1].setShader( self.loadShader("phase_3/models/shaders/filter-blurx.sha")) self.ssao[2].setShaderInput("src", ssao1) self.ssao[2].setShader( self.loadShader("phase_3/models/shaders/filter-blury.sha")) if ("Bloom" in configuration): bloomconf = configuration["Bloom"] bloom0 = self.textures["bloom0"] bloom1 = self.textures["bloom1"] bloom2 = self.textures["bloom2"] bloom3 = self.textures["bloom3"] if (bloomconf.size == "large"): scale = 8 downsampler = "phase_3/models/shaders/filter-down4.sha" elif (bloomconf.size == "medium"): scale = 4 downsampler = "phase_3/models/shaders/filter-copy.sha" else: scale = 2 downsampler = "phase_3/models/shaders/filter-copy.sha" self.bloom.append( self.manager.renderQuadInto(colortex=bloom0, div=2, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom1, div=scale, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom2, div=scale, align=scale)) self.bloom.append( self.manager.renderQuadInto(colortex=bloom3, div=scale, align=scale)) self.bloom[0].setShaderInput("src", self.textures["color"]) self.bloom[0].setShader( self.loadShader( "phase_3/models/shaders/filter-bloomi.sha")) self.bloom[1].setShaderInput("src", bloom0) self.bloom[1].setShader(self.loadShader(downsampler)) self.bloom[2].setShaderInput("src", bloom1) self.bloom[2].setShader( self.loadShader( "phase_3/models/shaders/filter-bloomx.sha")) self.bloom[3].setShaderInput("src", bloom2) self.bloom[3].setShader( self.loadShader( "phase_3/models/shaders/filter-bloomy.sha")) texcoords = {} texcoordPadding = {} for tex in needtexcoord: if self.textures[tex].getAutoTextureScale() != ATSNone or \ "HalfPixelShift" in configuration: texcoords[tex] = "l_texcoord_" + tex texcoordPadding["l_texcoord_" + tex] = tex else: # Share unpadded texture coordinates. texcoords[tex] = "l_texcoord" texcoordPadding["l_texcoord"] = None texcoordSets = list(enumerate(texcoordPadding.keys())) text = "//Cg\n" text += "void vshader(float4 vtx_position : POSITION,\n" text += " out float4 l_position : POSITION,\n" for texcoord, padTex in texcoordPadding.items(): if padTex is not None: text += " uniform float4 texpad_tx%s,\n" % (padTex) if ("HalfPixelShift" in configuration): text += " uniform float4 texpix_tx%s,\n" % (padTex) for i, name in texcoordSets: text += " out float2 %s : TEXCOORD%d,\n" % (name, i) text += " uniform float4x4 mat_modelproj)\n" text += "{\n" text += " l_position = mul(mat_modelproj, vtx_position);\n" for texcoord, padTex in texcoordPadding.items(): if padTex is None: text += " %s = vtx_position.xz * float2(0.5, 0.5) + float2(0.5, 0.5);\n" % ( texcoord) else: text += " %s = (vtx_position.xz * texpad_tx%s.xy) + texpad_tx%s.xy;\n" % ( texcoord, padTex, padTex) if ("HalfPixelShift" in configuration): text += " %s += texpix_tx%s.xy * 0.5;\n" % (texcoord, padTex) text += "}\n" if ("Exposure" in configuration): text += TONEMAP text += "void fshader(\n" for i, name in texcoordSets: text += " float2 %s : TEXCOORD%d,\n" % (name, i) for key in self.textures: text += " uniform sampler2D k_tx" + key + ",\n" if ("CartoonInk" in configuration): text += " uniform float4 k_cartoonseparation,\n" text += " uniform float4 k_cartooncolor,\n" text += " uniform float4 texpix_txaux,\n" if ("BlurSharpen" in configuration): text += " uniform float4 k_blurval,\n" if ("DOF" in configuration): text += " uniform float4 k_dofParams,\n" if ("VolumetricLighting" in configuration): text += " uniform float4 k_casterpos,\n" text += " uniform float4 k_vlparams,\n" if ("Exposure" in configuration): text += " uniform sampler1D k_exposuretex,\n" text += " out float4 o_color : COLOR)\n" text += "{\n" if ("FXAA" in configuration): text += " float4 result = tex2D(k_txfxaa, %s);\n" % ( texcoords["color"]) else: text += " float4 result = tex2D(k_txcolor, %s);\n" % ( texcoords["color"]) if ("CartoonInk" in configuration): text += CARTOON_BODY % {"texcoord": texcoords["aux"]} if ("AmbientOcclusion" in configuration): text += " result *= tex2D(k_txssao2, %s).r;\n" % ( texcoords["ssao2"]) if ("BlurSharpen" in configuration or "DOF" in configuration): text += " float blurFactor;\n" if ("DOF" in configuration): text += " float distance = k_dofParams.x;\n" text += " float range = k_dofParams.y;\n" text += " float near = k_dofParams.z;\n" text += " float far = k_dofParams.w;\n" text += " float depth = tex2D(k_txdepth, l_texcoord).r;\n" text += " float sceneZ = (-near * far) / (depth - far);\n" text += " blurFactor = 1 - saturate(abs(sceneZ - distance) / range);\n" if ("BlurSharpen" in configuration): text += " blurFactor *= k_blurval.x;\n" elif ("BlurSharpen" in configuration): text += " blurFactor = k_blurval.x;\n" text += " result = lerp(tex2D(k_txblur1, %s), result, blurFactor);\n" % ( texcoords["blur1"]) if ("Bloom" in configuration): #text += " result = saturate(result);\n"; text += " float4 bloom = 0.5 * tex2D(k_txbloom3, %s);\n" % ( texcoords["bloom3"]) text += " result = 1-((1-bloom)*(1-result));\n" if ("ViewGlow" in configuration): text += " result.r = result.a;\n" if ("VolumetricLighting" in configuration): text += " float decay = 1.0f;\n" text += " float2 curcoord = %s;\n" % (texcoords["color"]) text += " float2 lightdir = curcoord - k_casterpos.xy;\n" text += " lightdir *= k_vlparams.x;\n" text += " half4 sample = tex2D(k_txcolor, curcoord);\n" text += " float3 vlcolor = sample.rgb * sample.a;\n" text += " for (int i = 0; i < %s; i++) {\n" % (int( configuration["VolumetricLighting"].numsamples)) text += " curcoord -= lightdir;\n" text += " sample = tex2D(k_tx%s, curcoord);\n" % ( configuration["VolumetricLighting"].source) text += " sample *= sample.a * decay;//*weight\n" text += " vlcolor += sample.rgb;\n" text += " decay *= k_vlparams.y;\n" text += " }\n" text += " result += float4(vlcolor * k_vlparams.z, 1);\n" #if ("Exposure" in configuration): # text += " result.rgb = (result*result*result + result*result + result) / (result*result*result + result*result + result + 1);\n" if ("GammaAdjust" in configuration): gamma = configuration["GammaAdjust"] if gamma == 0.5: text += " result.rgb = sqrt(result.rgb);\n" elif gamma == 2.0: text += " result.rgb *= result.rgb;\n" elif gamma != 1.0: text += " result.rgb = pow(result.rgb, %ff);\n" % (gamma) if ("Inverted" in configuration): text += " result = float4(1, 1, 1, 1) - result;\n" if ("Exposure" in configuration): #text += " result = saturate(result);\n" text += " float exposure = tex1D(k_exposuretex, 0).r;\n" text += " result.rgb *= exposure;\n" #text += " result.rgb = float3(1.0) - exp(-result.rgb * exposure);\n" #text += " result.rgb = pow(result.rgb, float3(1.0 / 2.2));\n" else: text += " result.rgb *= %ff;\n" % (base.config.GetFloat( 'hdr-tonemapscale', 1.75)) text += " o_color = result;\n" text += "}\n" shader = Shader.make(text, Shader.SL_Cg) if not shader: return False self.finalQuad.setShader(shader) for tex in self.textures: self.finalQuad.setShaderInput("tx" + tex, self.textures[tex]) self.task = taskMgr.add(self.update, "common-filters-update") messenger.send("CICommonFilters_reconfigure") if (changed == "CartoonInk") or fullrebuild: if ("CartoonInk" in configuration): c = configuration["CartoonInk"] self.finalQuad.setShaderInput( "cartoonseparation", LVecBase4(c.separation, 0, c.separation, 0)) self.finalQuad.setShaderInput("cartooncolor", c.color) if (changed == "BlurSharpen") or fullrebuild: if ("BlurSharpen" in configuration): blurval = configuration["BlurSharpen"] self.finalQuad.setShaderInput( "blurval", LVecBase4(blurval, blurval, blurval, blurval)) if (changed == "DOF") or fullrebuild: if ("DOF" in configuration): conf = configuration["DOF"] self.finalQuad.setShaderInput( "dofParams", LVecBase4(conf.distance, conf.range, conf.near, conf.far)) if (changed == "Bloom") or fullrebuild: if ("Bloom" in configuration): bloomconf = configuration["Bloom"] intensity = bloomconf.intensity * 3.0 self.bloom[0].setShaderInput("blend", bloomconf.blendx, bloomconf.blendy, bloomconf.blendz, bloomconf.blendw * 2.0) self.bloom[0].setShaderInput( "trigger", bloomconf.mintrigger, 1.0 / (bloomconf.maxtrigger - bloomconf.mintrigger), 0.0, 0.0) self.bloom[0].setShaderInput("desat", bloomconf.desat) self.bloom[3].setShaderInput("intensity", intensity, intensity, intensity, intensity) if (changed == "VolumetricLighting") or fullrebuild: if ("VolumetricLighting" in configuration): config = configuration["VolumetricLighting"] tcparam = config.density / float(config.numsamples) self.finalQuad.setShaderInput("vlparams", tcparam, config.decay, config.exposure, 0.0) if (changed == "AmbientOcclusion") or fullrebuild: if ("AmbientOcclusion" in configuration): config = configuration["AmbientOcclusion"] self.ssao[0].setShaderInput("totalStrength", config.totalStrength) self.ssao[0].setShaderInput("base", config.base) self.ssao[0].setShaderInput("area", config.area) self.ssao[0].setShaderInput("falloff", config.falloff) self.ssao[0].setShaderInput("numSamples", config.numsamples) self.ssao[0].setShaderInput("radius", config.radius) if (changed == "Exposure") or fullrebuild: if ("Exposure" in configuration): self.finalQuad.setShaderInput( "exposuretex", configuration["Exposure"].exposureTex) self.update() return True