Пример #1
0
class ShadowedLightsPass(RenderPass):

    """ This pass processes all lights which have shadows """

    def __init__(self):
        RenderPass.__init__(self)

    def getID(self):
        return "ShadowedLightsPass"

    def getRequiredInputs(self):
        return {

            # Deferred target
            "data0": "DeferredScenePass.data0",
            "data1": "DeferredScenePass.data1",
            "data2": "DeferredScenePass.data2",
            "data3": "DeferredScenePass.data3",
            "depth": "DeferredScenePass.depth",


            # Lighting
            "lightsPerTileBuffer": "LightCullingPass.lightsPerTile",
            "lightingTileCount": "Variables.lightingTileCount",
            "lights": "Variables.allLights",
            "shadowAtlasPCF": "ShadowScenePass.atlasPCF",
            "shadowAtlas": "ShadowScenePass.atlas",
            "shadowSources": "Variables.allShadowSources",
            "directionToFace": "Variables.directionToFaceLookup",

            # IES Profiles
            "IESProfilesTex": "Variables.IESProfilesTex",

            "cameraPosition": "Variables.cameraPosition",
            "mainCam": "Variables.mainCam",
            "mainRender": "Variables.mainRender"

        }

    def create(self):
        self.target = RenderTarget("Shadowed Lights")
        self.target.addColorTexture()
        self.target.setColorBits(16)
        self.target.prepareOffscreenBuffer()
        self.target.setClearColor()
 
    def setShaders(self):
        shader = Shader.load(Shader.SLGLSL, 
            "Shader/DefaultPostProcess.vertex",
            "Shader/ShadowedLightsPass.fragment")
        self.target.setShader(shader)
        return [shader]

    def getOutputs(self):
        return {
            "ShadowedLightsPass.resultTex": lambda: self.target.getColorTexture(),
        }
class VolumetricLightingPass(RenderPass):

    """ This pass computes volumetric lighting at half screen resolution """

    def __init__(self):
        RenderPass.__init__(self)

    def getID(self):
        return "VolumetricLightingPass"

    def getRequiredInputs(self):
        return {

            # Deferred target
            "wsPositionTex": "DeferredScenePass.wsPosition",
            "wsNormalTex": "DeferredScenePass.wsNormal",
            "depthTex": "DeferredScenePass.depth",

            # Lighting
            "lightsPerTileBuffer": "LightCullingPass.lightsPerTile",
            "lightingTileCount": "Variables.lightingTileCount",
            "lights": "Variables.allLights",
            "shadowAtlasPCF": "ShadowScenePass.atlasPCF",
            "shadowAtlas": "ShadowScenePass.atlas",
            "shadowSources": "Variables.allShadowSources",
            "cameraPosition": "Variables.cameraPosition",
            "mainCam": "Variables.mainCam",
            "mainRender": "Variables.mainRender"
        }

    def create(self):
        self.target = RenderTarget("Volumetric Lighting")
        self.target.setHalfResolution()
        self.target.addColorTexture()
        self.target.prepareOffscreenBuffer()

    def setShaders(self):
        shader = Shader.load(Shader.SLGLSL, 
            "Shader/DefaultPostProcess.vertex",
            "Shader/VolumetricLighting.fragment")
        self.target.setShader(shader)

        return [shader]

    def setShaderInput(self, name, value, *args):
        self.target.setShaderInput(name, value, *args)
        # self.blurTarget.setShaderInput(name, value, *args)

    def getOutputs(self):
        return {
            "VolumetricLightingPass.resultTex": lambda: self.target.getColorTexture(),
        }
Пример #3
0
class OcclusionBlurPass(RenderPass):

    """ This pass performs a edge preserving blur by comparing the scene normals
    during the blur pass, aswell as as bilateral upscaling the occlusion input. """

    def __init__(self):
        RenderPass.__init__(self)

    def getID(self):
        return "OcclusionBlurPass"

    def getRequiredInputs(self):
        return {
            "sourceTex":  "AmbientOcclusionPass.computeResult", 
            "normalTex": "DeferredScenePass.wsNormal",
        }

    def create(self):
        self.targetV = RenderTarget("OcclusionBlurV")
        self.targetV.addColorTexture()
        self.targetV.setColorBits(16)
        self.targetV.prepareOffscreenBuffer()
 
        self.targetH = RenderTarget("OcclusionBlurH")
        self.targetH.addColorTexture()
        self.targetH.setColorBits(16)
        self.targetH.prepareOffscreenBuffer()

        self.targetH.setShaderInput("processedSourceTex", self.targetV.getColorTexture())

    def setShaders(self):
        shaderV = Shader.load(Shader.SLGLSL, 
            "Shader/DefaultPostProcess.vertex",
            "Shader/OcclusionBlurV.fragment")
        self.targetV.setShader(shaderV)

        shaderH = Shader.load(Shader.SLGLSL, 
            "Shader/DefaultPostProcess.vertex",
            "Shader/OcclusionBlurH.fragment")
        self.targetH.setShader(shaderH)

        return [shaderV, shaderH]

    def getOutputs(self):
        return {
            "OcclusionBlurPass.blurResult": lambda: self.targetH.getColorTexture(),
        }

    def setShaderInput(self, name, value):
        self.targetH.setShaderInput(name, value)
        self.targetV.setShaderInput(name, value)
class GlobalIlluminationPass(RenderPass):

    """ This pass performs voxel cone tracing over the previously generated
    voxel grid to compute a diffuse, specular and ambient term which can be
    used later in the lighting pass """

    def __init__(self):
        RenderPass.__init__(self)

    def getID(self):
        return "GlobalIlluminationPass"

    def getRequiredInputs(self):
        return {

            "data0": "DeferredScenePass.data0",
            "data1": "DeferredScenePass.data1",
            "data2": "DeferredScenePass.data2",
            "data3": "DeferredScenePass.data3",
            "giData": "Variables.giVoxelGridData",

            "cameraPosition": "Variables.cameraPosition",
            "mainCam": "Variables.mainCam",
            "mainRender": "Variables.mainRender"
        }

    def create(self):
        self.target = RenderTarget("GlobalIlluminationPass")
        self.target.setHalfResolution()
        self.target.addColorTexture()
        self.target.addAuxTexture()
        self.target.setColorBits(16)
        self.target.setAuxBits(16)
        self.target.prepareOffscreenBuffer()
 
    def setShaders(self):
        shader = Shader.load(Shader.SLGLSL, 
            "Shader/DefaultPostProcess.vertex",
            "Shader/ComputeGI.fragment")
        self.target.setShader(shader)
        
        return [shader]

    def getOutputs(self):
        return {
            "GlobalIlluminationPass.diffuseResult": lambda: self.target.getColorTexture(),
            "GlobalIlluminationPass.specularResult": lambda: self.target.getAuxTexture(0)
        }
Пример #5
0
class ScatteringPass(RenderPass):

    """ This pass computes the scattering if specified in the settings """

    def __init__(self):
        RenderPass.__init__(self)

    def getID(self):
        return "ScatteringPass"

    def getRequiredInputs(self):
        return {

            # Scattering
            "transmittanceSampler": ["Variables.transmittanceSampler", "Variables.emptyTextureWhite"],
            "inscatterSampler": ["Variables.inscatterSampler", "Variables.emptyTextureWhite"],
            "scatteringOptions": ["Variables.scatteringOptions", "Variables.null"],

            "mainRender": "Variables.mainRender",
            "cameraPosition": "Variables.cameraPosition",
            "mainCam": "Variables.mainCam",

            "wsPositionTex": "DeferredScenePass.wsPosition",
            "basecolorTex": "DeferredScenePass.data3"
            # "viewSpaceNormals": "ViewSpacePass.normals",
            # "viewSpacePosition": "ViewSpacePass.position"
        }

    def create(self):
        self.target = RenderTarget("Scattering")
        self.target.addColorTexture()
        self.target.setColorBits(16)
        self.target.prepareOffscreenBuffer()
 
    def setShaders(self):
        shader = Shader.load(Shader.SLGLSL, 
            "Shader/DefaultPostProcess.vertex",
            "Shader/ScatteringPass.fragment")
        self.target.setShader(shader)
        return [shader]

    def getOutputs(self):
        return {
            "ScatteringPass.resultTex": lambda: self.target.getColorTexture(),
        }
class AmbientOcclusionPass(RenderPass):

    """ This pass computes the screen space ambient occlusion if enabled in the
     settings. As many samples are required for a good looking result, the pass
     is done at half resolution and then upscaled by the edge preserving blur
     pass """

    def __init__(self):
        RenderPass.__init__(self)

    def getID(self):
        return "AmbientOcclusionPass"

    def getRequiredInputs(self):
        return {
            "frameIndex": "Variables.frameIndex",
            "mainRender": "Variables.mainRender",
            "mainCam": "Variables.mainCam",
            "noiseTexture": "Variables.noise4x4",
            "viewSpaceNormals": "ViewSpacePass.normals",
            "viewSpacePosition": "ViewSpacePass.position"
        }

    def create(self):
        self.target = RenderTarget("AmbientOcclusion")
        self.target.setHalfResolution()
        self.target.addColorTexture()
        self.target.prepareOffscreenBuffer()
 
    def setShaders(self):
        shader = Shader.load(Shader.SLGLSL, 
            "Shader/DefaultPostProcess.vertex",
            "Shader/ComputeOcclusion.fragment")
        self.target.setShader(shader)
        return [shader]

    def getOutputs(self):
        return {
            "AmbientOcclusionPass.computeResult": lambda: self.target.getColorTexture(),
        }
Пример #7
0
class LightCullingPass(RenderPass):

    """ This pass takes a list of all rendered lights and performs light culling
    per tile. The result is stored in a buffer which then can be used by the lighting
    pass to render the lights.

    The buffer maps 1 pixel per tile, so when using a tile size of 32 then there are 
    50x30 pixels if the window has a size of 1600*960. 

    To cull the lights, the scene depth texture is analyzed and the minimum and
    maximum depth per tile is extracted. We could use compute shaders for this task,
    but they are horribly slow. """

    def __init__(self):
        RenderPass.__init__(self)

    def getID(self):
        return "LightCullingPass"

    def setSize(self, sizeX, sizeY):
        """ Sets the amount of tiles. This is usally screenSize/tileSize """
        self.size = LVecBase2i(sizeX, sizeY)

    def setPatchSize(self, patchSizeX, patchSizeY):
        """ Sets the tile size in pixels """
        self.patchSize = LVecBase2i(patchSizeX, patchSizeY)

    def getRequiredInputs(self):
        return {
            "renderedLightsBuffer": "Variables.renderedLightsBuffer",
            "lights": "Variables.allLights",
            "depth": "DeferredScenePass.depth",
            "mainCam": "Variables.mainCam",
            "mainRender": "Variables.mainRender",
            "cameraPosition": "Variables.cameraPosition"
        }

    def create(self):
        self.target = RenderTarget("ComputeLightTileBounds")
        self.target.setSize(self.size.x, self.size.y)
        self.target.addColorTexture()
        self.target.prepareOffscreenBuffer()

        self.target.getColorTexture().setMagfilter(SamplerState.FTNearest)

        self.makePerTileStorage()
        self.target.setShaderInput("destinationBuffer", self.lightPerTileBuffer)

    def makePerTileStorage(self):
        """ Creates the buffer which stores which lights affect which tiles. 
        The first 16 entries are counters which store how many lights of that
        type were rendered, and the following entries store the light indices """
        self.tileStride = 0
        self.tileStride += 16 # Counters for the light types
        
        self.tileStride += LightLimits.maxPerTileLights["PointLight"]
        self.tileStride += LightLimits.maxPerTileLights["PointLightShadow"]

        self.tileStride += LightLimits.maxPerTileLights["DirectionalLight"]
        self.tileStride += LightLimits.maxPerTileLights["DirectionalLightShadow"]
        
        self.tileStride += LightLimits.maxPerTileLights["SpotLight"]
        self.tileStride += LightLimits.maxPerTileLights["SpotLightShadow"]

        tileBufferSize = self.size.x * self.size.y * self.tileStride
        self.lightPerTileBuffer = Texture("LightsPerTileBuffer")
        self.lightPerTileBuffer.setupBufferTexture(
            tileBufferSize, Texture.TInt, Texture.FR32i, GeomEnums.UHDynamic)

        MemoryMonitor.addTexture("Light Per Tile Buffer", self.lightPerTileBuffer)

    def getDefines(self):
        return {
            "LIGHTING_PER_TILE_STRIDE": self.tileStride
        }
 
    def setShaders(self):
        shader = Shader.load(Shader.SLGLSL, 
            "Shader/DefaultPostProcess.vertex",
            "Shader/PrecomputeLights.fragment")
        self.target.setShader(shader)

        return [shader]

    def getOutputs(self):
        return {
            "LightCullingPass.lightsPerTile": lambda: self.lightPerTileBuffer
        }
Пример #8
0
    const int cmap_size = """ + str(sz) + """;
    ivec2 coord = ivec2(gl_FragCoord.xy + 0.5);
    vec2 lc = coord / float(cmap_size);
    lc.y = 1.0 - lc.y;
    lc.y *= lc.x;

    vec3 baseDir = normalize(vec3(1, lc.x, lc.y));
   
    vec3 minimumError = FindMinimumQuantizationError(baseDir);

    float res = minimumError.x;

    res /= max(abs(baseDir.x), max(abs(baseDir.y), abs(baseDir.z)));

    result.xyz = vec3(res);
    result.w = 1.0;


}


"""

target.setShader(Shader.make(Shader.SLGLSL, vertex_shader, fragment_shader))

base.graphicsEngine.renderFrame()

k = target.getColorTexture()
base.graphicsEngine.extractTextureData(k, base.win.getGsg())
k.write("NormalQuantizationTex.png")
    vec2 lc = coord / float(cmap_size);
    lc.y = 1.0 - lc.y;
    lc.y *= lc.x;

    vec3 baseDir = normalize(vec3(1, lc.x, lc.y));
   
    vec3 minimumError = FindMinimumQuantizationError(baseDir);

    float res = minimumError.x;

    res /= max(abs(baseDir.x), max(abs(baseDir.y), abs(baseDir.z)));

    result.xyz = vec3(res);
    result.w = 1.0;


}


"""


target.setShader(Shader.make(Shader.SLGLSL, vertex_shader, fragment_shader))

base.graphicsEngine.renderFrame()

k = target.getColorTexture()
base.graphicsEngine.extractTextureData(k, base.win.getGsg())
k.write("NormalQuantizationTex.png")

Пример #10
0
class DynamicExposurePass(RenderPass):

    """ This pass handles the dynamic exposure feature, it downscales the
    Scene to get the average brightness and then outputs a new exposure which
    can be used by the lighting pass. """

    def __init__(self, pipeline):
        RenderPass.__init__(self)
        self.pipeline = pipeline

        # Create the storage for the exposure. We cannot simply use the color output
        # as the RenderTargetMatcher would have problems with that (Circular Reference)
        self.lastExposureStorage = Texture("Last Exposure")
        self.lastExposureStorage.setup2dTexture(1, 1, Texture.TFloat, Texture.FR32)

        # Registers the texture so the lighting pass can use it
        self.pipeline.renderPassManager.registerStaticVariable(
            "dynamicExposureTex", self.lastExposureStorage)


    def getID(self):
        return "DynamicExposurePass"

    def getRequiredInputs(self):
        return {
            "colorTex": "LightingPass.resultTex",
            "dt": "Variables.frameDelta"
        }

    def create(self):

        # Fetch the original texture size from the window size
        size = LVecBase2i(Globals.base.win.getXSize(), Globals.base.win.getYSize())

        # Create the first downscale pass which reads the scene texture, does a 
        # 2x2 inplace box filter, and then converts the result to luminance. 
        # Using luminance allows faster downscaling, as we can use texelGather then
        self.downscalePass0 = RenderTarget("Downscale Initial")
        self.downscalePass0.addColorTexture()
        self.downscalePass0.setSize(size.x / 2, size.y / 2)
        self.downscalePass0.prepareOffscreenBuffer()

        # Store the current size of the pass
        workSizeX, workSizeY = int(size.x / 2), int(size.y / 2)

        self.downscalePasses = []
        passIdx = 0
        lastTex = self.downscalePass0.getColorTexture()

        # Scale the scene until there are only a few pixels left. Each pass does a 
        # 4x4 inplace box filter, which is cheap because we can sample the luminance
        # only.
        while workSizeX * workSizeY > 128:
            workSizeX /= 4
            workSizeY /= 4
            passIdx += 1
            scalePass = RenderTarget("Downscale Pass " + str(passIdx))
            scalePass.setSize(workSizeX, workSizeY)
            scalePass.addColorTexture()
            scalePass.prepareOffscreenBuffer()
            scalePass.setShaderInput("luminanceTex", lastTex)
            lastTex = scalePass.getColorTexture()
            self.downscalePasses.append(scalePass)

        # Create the final pass which computes the average of all left pixels,
        # compares that with the last exposure and stores the difference.
        self.finalDownsamplePass = RenderTarget("Downscale Final")
        self.finalDownsamplePass.setSize(1, 1)
        # self.finalDownsamplePass.setColorBits(16)
        # self.finalDownsamplePass.addColorTexture()
        self.finalDownsamplePass.setColorWrite(False)
        self.finalDownsamplePass.prepareOffscreenBuffer()
        self.finalDownsamplePass.setShaderInput("luminanceTex", lastTex)
        self.finalDownsamplePass.setShaderInput("targetExposure", 
            self.pipeline.settings.targetExposure)
        self.finalDownsamplePass.setShaderInput("adaptionSpeed", 
            self.pipeline.settings.brightnessAdaptionSpeed)

        # Clear the storage in the beginning
        self.lastExposureStorage.setClearColor(Vec4(0))
        self.lastExposureStorage.clearImage()

        # Set defines and other inputs
        self.finalDownsamplePass.setShaderInput("lastExposureTex", self.lastExposureStorage)
        self.pipeline.renderPassManager.registerDefine("USE_DYNAMIC_EXPOSURE", 1)

    def setShaders(self):
        shaderFirstPass = Shader.load(Shader.SLGLSL, 
            "Shader/DefaultPostProcess.vertex",
            "Shader/DownsampleFirstPass.fragment")
        self.downscalePass0.setShader(shaderFirstPass)

        shaderDownsample = Shader.load(Shader.SLGLSL, 
            "Shader/DefaultPostProcess.vertex",
            "Shader/Downsample.fragment")
        for scalePass in self.downscalePasses:
            scalePass.setShader(shaderDownsample)

        shaderFinal = Shader.load(Shader.SLGLSL, 
            "Shader/DefaultPostProcess.vertex",
            "Shader/DownsampleFinalPass.fragment")
        self.finalDownsamplePass.setShader(shaderFinal)

        return [shaderFirstPass, shaderDownsample, shaderFinal]

    def setShaderInput(self, name, value, *args):
        self.downscalePass0.setShaderInput(name, value, *args)
        self.finalDownsamplePass.setShaderInput(name, value, *args)

    def getOutputs(self):
        return {
        }
Пример #11
0
size = 1024
mipidx = 0
blurF = 0.5
while size > 1:
    size /= 2
    blurF *= 1.5

    target = RenderTarget("precompute cubemap")
    target.addColorTexture()
    target.setSize(size, size)
    target.prepareOffscreenBuffer()

    stex = target.getColorTexture()

    target.setShader(shader)
    target.setShaderInput("sourceMap", envmap)
    target.setShaderInput("mipIndex", mipidx)
    target.setShaderInput("blurFactor", blurF)

    for i in xrange(6):

        print "Generating face", i,"for mipmap",mipidx
        target.setShaderInput("directionIndex", i)
        base.graphicsEngine.renderFrame()
        base.graphicsEngine.extractTextureData(stex, base.win.getGsg())

        stex.write("result/" + str(mipidx) + "_" + str(i) + ".png")

    target.deleteBuffer()
    mipidx += 1
Пример #12
0
size = 1024
mipidx = 0
blurF = 0.5
while size > 1:
    size /= 2
    blurF *= 1.5

    target = RenderTarget("precompute cubemap")
    target.addColorTexture()
    target.setSize(size, size)
    target.prepareOffscreenBuffer()

    stex = target.getColorTexture()

    target.setShader(shader)
    target.setShaderInput("sourceMap", envmap)
    target.setShaderInput("mipIndex", mipidx)
    target.setShaderInput("blurFactor", blurF)

    for i in xrange(6):

        print "Generating face", i, "for mipmap", mipidx
        target.setShaderInput("directionIndex", i)
        base.graphicsEngine.renderFrame()
        base.graphicsEngine.extractTextureData(stex, base.win.getGsg())

        stex.write("result/" + str(mipidx) + "_" + str(i) + ".png")

    target.deleteBuffer()
    mipidx += 1