codepad
[
create a new paste
]
login
|
about
Language:
C
C++
D
Haskell
Lua
OCaml
PHP
Perl
Plain Text
Python
Ruby
Scheme
Tcl
module cg; private { import core.dllStuff; import core.plugin; import core.common; import renderer.renderer; import geometry.vertex; import geometry.vertexData; import derelict.opengl.gl; import glExtLoader; import derelict.cg.cg; import derelict.cgGL.cgGL; import core.maths; import std.string; import subsystems.texture; import renderer.gpuShader; import renderer.typedefs; import renderer.vertexKernel; import renderer.gpuShaderKernel; import renderer.gpuShaderState; import renderer.textureKernel; import renderer.textureState; import renderer.renderContextBuilder; import core.engine; import core.engineSubsystem; import core.systemCaps; import subsystems.render; import subsystems.gpuShader; } pragma (lib, "derelictGL.lib"); pragma (lib, "derelictCg.lib"); pragma (lib, "derelictCgGL.lib"); pragma (lib, "derelictUtil.lib"); class CgException : Exception { this (char[] str) { super(str); } } private class CgCaps : SystemCaps { this () { set("loaded", true); engine.systemCaps.extend(this, "Cg"); } } private class CgShaderSubsystem : GpuShaderSubsystem { private static void cgErrorCallback() { CGerror error = cgGetError(); char* errStr; if (error == CGerror.COMPILER_ERROR) { errStr = cgGetLastListing(cgContext); } else { errStr = cgGetErrorString(error); } throw new CgException("cgError: " ~ errStr[0 .. strlen(errStr)]); } this () { //writefln("Initializing Cg"); DerelictCG_Load(); DerelictCGGL_Load(); cgContext = cgCreateContext(); cgSetErrorCallback(&cgErrorCallback); } private bool loadCgProgram(char[] programString, CGprofile profile, out CGprogram cgProg) { if (!cgGLIsProfileSupported(profile)) { return false; } char[] progStr = programString.replace("/+", "/*").replace("+/", "*/") ~ '\0'; CGprogram prog; try { prog = cgCreateProgram(cgContext, CGenum.SOURCE, progStr, profile, "main", null); cgGLLoadProgram(prog); } catch (CgException err) { writefln(err); return false; } finally { delete progStr; } cgProg = prog; return true; } IVertexShader loadVertexShader(char[] programString) { CGprogram prog; if (CgShaderKernel.vertexShadersSupported && loadCgProgram(programString, vertexProfile, prog)) { return new CgVertexShader(prog); } else { return null; } } IFragmentShader loadFragmentShader(char[] programString) { CGprogram prog; if (CgShaderKernel.fragmentShadersSupported && loadCgProgram(programString, fragmentProfile, prog)) { return new CgFragmentShader(prog); } else { return null; } } package { static CGcontext cgContext; static CGprofile vertexProfile; static CGprofile fragmentProfile; } } private class CgVertexKernel : VertexKernel { private VertexKernel old; this (VertexKernel old) { this.old = old; } void enableArray(VertexDataType vdt, VertexStoreType vst, uint stride, void* ptr) { if (!CgShaderKernel.vertexShaderBound) { return old.enableArray(vdt, vst, stride, ptr); } uint components; uint type; switch (vst) { case VertexStoreType.FLOAT: case VertexStoreType.FLOAT2: case VertexStoreType.FLOAT3: case VertexStoreType.FLOAT4: { type = GL_FLOAT; components = vst - VertexStoreType.FLOAT + 1; } break; case VertexStoreType.INT: { type = GL_INT; components = 1; } break; case VertexStoreType.INT1: case VertexStoreType.INT2: case VertexStoreType.INT3: case VertexStoreType.INT4: { type = GL_INT; components = vst - VertexStoreType.INT1 + 1; } break; case VertexStoreType.BYTE1: case VertexStoreType.BYTE2: case VertexStoreType.BYTE3: case VertexStoreType.BYTE4: { type = GL_BYTE; components = vst - VertexStoreType.BYTE1 + 1; } break; default: throw new Exception("*Renderer: invalid vertex attribute format"); } enableArray(vdt); cgGLSetParameterPointer(cgParams[vdt - arrayOffset], components, type, stride, ptr); } private void enableArray(VertexDataType vdt) { CGparameter cgParam = cgParams[vdt - arrayOffset]; if (cgParam) { debug writefln("disable vdt: %s cg param: %s", cast(uint)vdt, cast(uint)cgParam); cgGLEnableClientState(cgParam); } } void disableArray(VertexDataType vdt) { if (!CgShaderKernel.vertexShaderBound) { return old.disableArray(vdt); } CGparameter cgParam = cgParams[vdt - arrayOffset]; if (cgParam) { debug writefln("disable vdt: %s cg param: %s", cast(uint)vdt, cast(uint)cgParam); cgGLDisableClientState(cgParam); } } package { static const uint arraySize = cast(uint)(VertexDataType.max - VertexDataType.min + 1); static const uint arrayOffset = cast(uint)VertexDataType.min; static CGparameter[arraySize] cgParams; } } class CgShaderKernel : GPUShaderKernel { private GPUShaderKernel old; this(GPUShaderKernel old) { this.old = old; if (!cgInitialized) { writefln("Initializing CgGL"); DerelictGL_Load(); loadAllOpenGLExtensions(); try { CgShaderSubsystem.vertexProfile = cgGLGetLatestProfile(CGGLenum.VERTEX); CgShaderSubsystem.fragmentProfile = cgGLGetLatestProfile(CGGLenum.FRAGMENT); if (cgGLIsProfileSupported(CgShaderSubsystem.vertexProfile)) { cgGLSetOptimalOptions(CgShaderSubsystem.vertexProfile); vertexShadersSupported = true; } if (cgGLIsProfileSupported(CgShaderSubsystem.fragmentProfile)) { cgGLSetOptimalOptions(CgShaderSubsystem.fragmentProfile); fragmentShadersSupported = true; } writefln("CgGL initialization finished"); } catch (CgException err) { writefln("Cg is not supported\nError: ", err); } cgInitialized = true; } } void apply(inout GPUShaderState state) { old.apply(state); with (state) { if (!applyState) { return; } vertexShaderBound = (vertexShader !is null); fragmentShaderBound = (fragmentShader !is null); } } void unapply(inout GPUShaderState state) { old.unapply(state); with (state) { if (!applyState) { return; } vertexShaderBound = false; fragmentShaderBound = false; } } private { static bool cgInitialized = false; } package { static bool vertexShadersSupported = false; static bool fragmentShadersSupported = false; static bool vertexShaderBound = false; static bool fragmentShaderBound = false; } } class CgTextureKernel : TextureKernel { private TextureKernel old; this(TextureKernel old) { this.old = old; } void apply(inout TextureState state) { with (state) { if (!applyState) { return; } foreach (uint i, Texture t; texUnitTextures) { if (t !is null) { state.texUnits[i].bindTexture(t); } } } old.apply(state); } void unapply(inout TextureState state) { foreach (inout Texture t; texUnitTextures) { t = null; } old.unapply(state); } package { static Texture[TextureState.maxTexUnits] texUnitTextures; } } private template MCgProgram() { ShaderParam getParam(char[] name) { return cgGetNamedParameter(cgProgram, name ~ '\0'); } void setParam(ShaderParam param, float val) { cgGLSetParameter1f(cast(CGparameter)param, val); } void setParam(ShaderParam param, vec2 val) { cgGLSetParameter2fv(cast(CGparameter)param, &val.x); } void setParam(ShaderParam param, vec3 val) { cgGLSetParameter3fv(cast(CGparameter)param, &val.x); } void setParam(ShaderParam param, vec4 val) { cgGLSetParameter4fv(cast(CGparameter)param, &val.x); } void setParam(ShaderParam param, mat4 val) { cgGLSetMatrixParameterfr(cast(CGparameter)param, &val.data[0]); } void setStateMatrixParam(ShaderParam param, StateMatrix sm, MatrixTransform mt) { cgGLSetStateMatrixParameter(cast(CGparameter)param, cast(CGGLenum)sm, cast(CGGLenum)mt); } package { CGprogram cgProgram; } } class CgVertexShader : IVertexShader { mixin MCgProgram; private void extractVaryingParams() { CGparameter leaf = cgGetFirstLeafParameter(cgProgram, CGenum.PROGRAM); while (leaf) { CGenum var = cgGetParameterVariability(leaf); CGenum dir = cgGetParameterDirection(leaf); if (var == CGenum.VARYING && dir != CGenum.OUT && dir != CGenum.ERROR) { CGresource res = cgGetParameterResource(leaf); if (res >= VertexDataType.min && res <= VertexDataType.max) { VertexDataType vdt = cast(VertexDataType)res; varyingParams ~= VaryingParam(leaf, vdt); debug writefln("extracted a param: ", cast(uint)vdt); } } leaf = cgGetNextLeafParameter(leaf); } } void bind() { foreach (inout VaryingParam vpar; varyingParams) { CgVertexKernel.cgParams[vpar.succ - CgVertexKernel.arrayOffset] = vpar.pred; } cgGLEnableProfile(CgShaderSubsystem.vertexProfile); cgGLBindProgram(cgProgram); } void unbind() { foreach (inout VaryingParam vpar; varyingParams) { CgVertexKernel.cgParams[vpar.succ - CgVertexKernel.arrayOffset] = null; } cgGLUnbindProgram(CgShaderSubsystem.vertexProfile); cgGLDisableProfile(CgShaderSubsystem.vertexProfile); } this (CGprogram prog) { this.cgProgram = prog; extractVaryingParams(); } bool isVertexDataNeeded(VertexDataType vdt) { foreach (inout VaryingParam vp; varyingParams) { if (vp.succ == vdt) { return true; } } return false; } void setTexture(ShaderParam param, Texture tex) { assert (false); // not implemented } package { alias tuple!(CGparameter, VertexDataType) VaryingParam; VaryingParam[] varyingParams; } } class CgFragmentShader : IFragmentShader { mixin MCgProgram; private void extractTexBindings() { CGparameter leaf = cgGetFirstLeafParameter(cgProgram, CGenum.PROGRAM); while (leaf) { CGenum var = cgGetParameterVariability(leaf); CGenum dir = cgGetParameterDirection(leaf); if (var != CGenum.VARYING && dir != CGenum.OUT && dir != CGenum.ERROR) { CGresource res = cgGetParameterResource(leaf); if (res >= CGresource.TEXUNIT0 && res <= CGresource.TEXUNIT15) { texBindings ~= TexBinding(leaf, res - CGresource.TEXUNIT0); } } leaf = cgGetNextLeafParameter(leaf); } } this (CGprogram prog) { this.cgProgram = prog; extractTexBindings(); } void setTexture(ShaderParam param, Texture tex) { if (tex !is null && tex.id != -1) { foreach (inout TexBinding tb; texBindings) { if (tb.pred == cast(CGparameter)param) { CgTextureKernel.texUnitTextures[tb.succ] = tex; return; } } } } void bind() { cgGLEnableProfile(CgShaderSubsystem.fragmentProfile); cgGLBindProgram(cgProgram); } void unbind() { cgGLUnbindProgram(CgShaderSubsystem.fragmentProfile); cgGLDisableProfile(CgShaderSubsystem.fragmentProfile); } package { alias tuple!(CGparameter, uint) TexBinding; TexBinding[] texBindings; } } class CgVertexKernelFactory : VertexKernelFactory { VertexKernel create() { return new CgVertexKernel(old.create); } this (VertexKernelFactory old) { this.old = old; } private VertexKernelFactory old; } class CgShaderKernelFactory : GPUShaderKernelFactory { GPUShaderKernel create() { return new CgShaderKernel(old.create); } this (GPUShaderKernelFactory old) { this.old = old; } private GPUShaderKernelFactory old; } class CgTextureKernelFactory : TextureKernelFactory { TextureKernel create() { return new CgTextureKernel(old.create); } this (TextureKernelFactory old) { this.old = old; } private TextureKernelFactory old; } void initializeCg() { engine.registerSubsystem(new CgShaderSubsystem); with (subsystem!(RenderSubsystem).renderContextBuilder()) { vertexKF = new CgVertexKernelFactory(vertexKF); gpuShaderKF = new CgShaderKernelFactory(gpuShaderKF); textureKF = new CgTextureKernelFactory(textureKF); } new CgCaps; // tell the engine that Cg is supported from now on } class CgPlugin : IPlugin { static class CgComponent : IPluginComponent { char[] name() { return "opengl.cg"; } char[][] dependencies() { static char[][] deps = ["opengl.window", "opengl.renderer"]; return deps; } bool initialize(IPluginInterface pi) { initializeCg(); return true; } } IPluginComponent[] components() { static IPluginComponent[1] comp; if (comp[0] is null) { comp[0] = new CgComponent; } return comp; } } export extern(C) IPlugin createPlugin() { //writefln("cg.createPlugin called"); return new CgPlugin; }
Private
[
?
]
Run code