private bool IsFluidFaceVisible(int curLevel, int nX, int nY, int nZ, Block neighbor, int neighborFace) { if (neighborFace == Direction.Down && curLevel < 5) { return(true); } CullType cull = neighbor.GetCullType(neighborFace); if (cull == CullType.Solid || cull == CullType.Cutout) { return(false); } if (cull == CullType.Transparent) { if (!neighbor.IsFluid()) { return(false); } if (neighborFace == Direction.Up || neighborFace == Direction.Down) { return(false); } return(neighbor.FluidLevel < curLevel); } return(true); }
/// <summary> /// 设置CullingGroup的距离分区 /// 例如传入三个值,10,20,30 /// 如果距离在10以内,代表摄像机范围 /// 如果距离在20以内,代表超出范围 /// 如果距离在30以内,代表足够远,超出则代表非常远 /// </summary> /// <param name="_distanceBands"></param> public void SetDistanceBands(params float[] _distanceBands) { if (cullType == CullType.ViewCull) { cullingGroup.onStateChanged = OnStateDistanceChanged; cullType = CullType.DistanceCull; } cullingGroup.SetBoundingDistances(_distanceBands); }
public ViewCullingGroup(int _maxSize) { maxSize = _maxSize; currentRequestingCount = 0; cullingGroup = new CullingGroup(); boundingSpheres = new BoundingSphere[maxSize]; viewCullingObjects = new IViewCullingObject[maxSize]; cullingGroup.onStateChanged = OnStateVisibilityChanged; cullType = CullType.ViewCull; cullingGroup.SetBoundingSpheres(boundingSpheres); cullingGroup.SetBoundingSphereCount(currentRequestingCount); }
public bool IsFaceVisible(Block neighbor, int face) { switch (ID) { case BlockID.TallGrass: return(true); case BlockID.Cloud: CullType cull = neighbor.GetCullType(face); if (cull == CullType.Solid || cull == CullType.Cutout) { return(false); } if (cull == CullType.Transparent) { return(neighbor.IsFluid()); } return(true); case BlockID.Leaves: if (neighbor.ID == BlockID.Leaves) { if (face == Direction.Left || face == Direction.Back || face == Direction.Down) { return(false); } return(true); } goto default; default: return(neighbor.GetCullType(face) != CullType.Solid); } }
/// <summary> /// This handles the flipping needed when the view being rendered is a mirrored view. /// </summary> /// <param name="type"></param> private void SetCull(CullType type) { if(_state.FaceCulling == type) { return; } if(type == CullType.TwoSided) { // TODO: Gl.glDisable(Gl.GL_CULL_FACE); } else { if(_state.FaceCulling == CullType.TwoSided) { // TODO: Gl.glDisable(Gl.GL_CULL_FACE); } if(type == CullType.TwoSided) { if(_viewDef.IsMirror == true) { // TODO: Gl.glCullFace(Gl.GL_FRONT); } else { // TODO: Gl.glCullFace(Gl.GL_BACK); } } else { if(_viewDef.IsMirror == true) { // TODO: Gl.glCullFace(Gl.GL_BACK); } else { // TODO: Gl.glCullFace(Gl.GL_FRONT); } } } _state.FaceCulling = type; }
/// <summary> /// Parses the material, if there are any errors during parsing the defaultShader will be set. /// </summary> /// <param name="lexer"></param> private void ParseMaterial(idLexer lexer) { _registerCount = PredefinedRegisterCount; // leave space for the parms to be copied in. for(int i = 0; i < _registerCount; i++) { _parsingData.RegisterIsTemporary[i] = true; // they aren't constants that can be folded. } TextureRepeat textureRepeatDefault = TextureRepeat.Repeat; // allow a global setting for repeat. idToken token = null; string tokenValue; string tokenLower; int count; while(true) { if(TestMaterialFlag(Renderer.MaterialFlags.Defaulted) == true) { // we have a parse error. return; } if((token = lexer.ExpectAnyToken()) == null) { this.MaterialFlag = MaterialFlags.Defaulted; return; } tokenValue = token.ToString(); tokenLower = tokenValue.ToLower(); // end of material definition if(tokenLower == "}") { break; } else if(tokenLower == "qer_editorimage") { token = lexer.ReadTokenOnLine(); _editorImageName = (token != null) ? token.ToString() : string.Empty; lexer.SkipRestOfLine(); } else if(tokenLower == "description") { token = lexer.ReadTokenOnLine(); _description = (token != null) ? token.ToString() : string.Empty; } // check for the surface / content bit flags. else if(CheckSurfaceParameter(token) == true) { } else if(tokenLower == "polygonoffset") { this.MaterialFlag = Renderer.MaterialFlags.PolygonOffset; if((token = lexer.ReadTokenOnLine()) == null) { _polygonOffset = 1; } else { _polygonOffset = token.ToFloat(); } } // noshadow. else if(tokenLower == "noshadows") { this.MaterialFlag = MaterialFlags.NoShadows; } else if(tokenLower == "suppressinsubview") { _suppressInSubview = true; } else if(tokenLower == "portalsky") { _portalSky = true; } else if(tokenLower == "noselfshadow") { this.MaterialFlag = Renderer.MaterialFlags.NoSelfShadow; } else if(tokenLower == "noportalfog") { this.MaterialFlag = Renderer.MaterialFlags.NoPortalFog; } // forceShadows allows nodraw surfaces to cast shadows. else if(tokenLower == "forceshadows") { this.MaterialFlag = Renderer.MaterialFlags.ForceShadows; } // overlay / decal suppression. else if(tokenLower == "nooverlays") { _allowOverlays = false; } // moster blood overlay forcing for alpha tested or translucent surfaces. else if(tokenLower == "forceoverlays") { _parsingData.ForceOverlays = true; } else if(tokenLower == "translucent") { _coverage = MaterialCoverage.Translucent; } // global zero clamp. else if(tokenLower == "zeroclamp") { textureRepeatDefault = TextureRepeat.ClampToZero; } // global clamp. else if(tokenLower == "clamp") { textureRepeatDefault = TextureRepeat.Clamp; } // global clamp. else if(tokenLower == "alphazeroclamp") { textureRepeatDefault = TextureRepeat.ClampToZero; } // forceOpaque is used for skies-behind-windows. else if(tokenLower == "forceopaque") { _coverage = MaterialCoverage.Opaque; } else if(tokenLower == "twosided") { _cullType = CullType.TwoSided; // twoSided implies no-shadows, because the shadow // volume would be coplanar with the surface, giving depth fighting // we could make this no-self-shadows, but it may be more important // to receive shadows from no-self-shadow monsters. this.MaterialFlag = Renderer.MaterialFlags.NoShadows; } else if(tokenLower == "backsided") { _cullType = CullType.Back; // the shadow code doesn't handle this, so just disable shadows. // We could fix this in the future if there was a need. this.MaterialFlag = Renderer.MaterialFlags.NoShadows; } else if(tokenLower == "foglight") { _fogLight = true; } else if(tokenLower == "blendlight") { _blendLight = true; } else if(tokenLower == "ambientlight") { _ambientLight = true; } else if(tokenLower == "mirror") { _sort = (float) MaterialSort.Subview; _coverage = MaterialCoverage.Opaque; } else if(tokenLower == "nofog") { _noFog = true; } else if(tokenLower == "unsmoothedtangents") { _unsmoothedTangents = true; } // lightFallofImage <imageprogram> // specifies the image to use for the third axis of projected // light volumes. else if(tokenLower == "lightfalloffimage") { _lightFalloffImage = idE.ImageManager.ImageFromFile(ParsePastImageProgram(lexer), TextureFilter.Default, false, TextureRepeat.Clamp, TextureDepth.Default); } // guisurf <guifile> | guisurf entity // an entity guisurf must have an idUserInterface // specified in the renderEntity. else if(tokenLower == "guisurf") { token = lexer.ReadTokenOnLine(); tokenLower = token.ToString().ToLower(); if(tokenLower == "entity") { _entityGui = 1; } else if(tokenLower == "entity2") { _entityGui = 2; } else if(tokenLower == "entity3") { _entityGui = 3; } else { _userInterface = idE.UIManager.FindInterface(token.ToString(), true); } } // sort. else if(tokenLower == "sort") { ParseSort(lexer); } // spectrum <integer>. else if(tokenLower == "spectrum") { int.TryParse(lexer.ReadTokenOnLine().ToString(), out _spectrum); } // deform < sprite | tube | flare >. else if(tokenLower == "deform") { ParseDeform(lexer); } // decalInfo <staySeconds> <fadeSeconds> (<start rgb>) (<end rgb>). else if(tokenLower == "decalinfo") { ParseDecalInfo(lexer); } // renderbump <args...>. else if(tokenLower == "renderbump") { _renderBump = lexer.ParseRestOfLine(); } // diffusemap for stage shortcut. else if(tokenLower == "diffusemap") { idLexer newLexer = new idLexer(LexerOptions.NoFatalErrors | LexerOptions.NoStringConcatination | LexerOptions.NoStringEscapeCharacters | LexerOptions.AllowPathNames); newLexer.LoadMemory(string.Format("blend diffusemap\nmap {0}\n}}\n", ParsePastImageProgram(lexer)), "diffusemap"); ParseStage(newLexer, textureRepeatDefault); } // specularmap for stage shortcut. else if(tokenLower == "specularmap") { idLexer newLexer = new idLexer(LexerOptions.NoFatalErrors | LexerOptions.NoStringConcatination | LexerOptions.NoStringEscapeCharacters | LexerOptions.AllowPathNames); newLexer.LoadMemory(string.Format("blend specularmap\nmap {0}\n}}\n", ParsePastImageProgram(lexer)), "specularmap"); ParseStage(newLexer, textureRepeatDefault); } // normalmap for stage shortcut. else if(tokenLower == "bumpmap") { idLexer newLexer = new idLexer(LexerOptions.NoFatalErrors | LexerOptions.NoStringConcatination | LexerOptions.NoStringEscapeCharacters | LexerOptions.AllowPathNames); newLexer.LoadMemory(string.Format("blend bumpmap\nmap {0}\n}}\n", ParsePastImageProgram(lexer)), "bumpmap"); ParseStage(newLexer, textureRepeatDefault); } // DECAL_MACRO for backwards compatibility with the preprocessor macros. else if(tokenLower == "decal_macro") { // polygonOffset this.MaterialFlag = Renderer.MaterialFlags.PolygonOffset; _polygonOffset = -1; // discrete _surfaceFlags |= SurfaceFlags.Discrete; _contentFlags &= ~ContentFlags.Solid; // sort decal. _sort = (float) MaterialSort.Decal; // noShadows this.MaterialFlag = Renderer.MaterialFlags.NoShadows; } else if(tokenValue == "{") { // create the new stage. ParseStage(lexer, textureRepeatDefault); } else { idConsole.WriteLine("unknown general material parameter '{0}' in '{1}'", tokenValue, this.Name); return; } } // add _flat or _white stages if needed. AddImplicitStages(); // order the diffuse / bump / specular stages properly. SortInteractionStages(); // if we need to do anything with normals (lighting or environment mapping) // and two sided lighting was asked for, flag // shouldCreateBackSides() and change culling back to single sided, // so we get proper tangent vectors on both sides. // we can't just call ReceivesLighting(), because the stages are still // in temporary form. if(_cullType == CullType.TwoSided) { count = _parsingData.Stages.Count; for(int i = 0; i < count; i++) { if((_parsingData.Stages[i].Lighting != StageLighting.Ambient) || (_parsingData.Stages[i].Texture.TextureCoordinates != TextureCoordinateGeneration.Explicit)) { if(_cullType == CullType.TwoSided) { _cullType = CullType.Front; _shouldCreateBackSides = true; } break; } } } // currently a surface can only have one unique texgen for all the stages on old hardware. TextureCoordinateGeneration firstGen = TextureCoordinateGeneration.Explicit; count = _parsingData.Stages.Count; for(int i = 0; i < count; i++) { if(_parsingData.Stages[i].Texture.TextureCoordinates != TextureCoordinateGeneration.Explicit) { if(firstGen == TextureCoordinateGeneration.Explicit) { firstGen = _parsingData.Stages[i].Texture.TextureCoordinates; } else if(firstGen != _parsingData.Stages[i].Texture.TextureCoordinates) { idConsole.Warning("material '{0}' has multiple stages with a texgen", this.Name); break; } } } }
private void Clear() { _description = "<none>"; _renderBump = string.Empty; _contentFlags = ContentFlags.Solid; _surfaceFlags = SurfaceFlags.None; _materialFlags = 0; _sort = (float) MaterialSort.Bad; _coverage = MaterialCoverage.Bad; _cullType = CullType.Front; _deformType = DeformType.None; _deformRegisters = new int[4]; _ops = null; _expressionRegisters = null; _constantRegisters = null; _stages = new MaterialStage[] { }; _stageCount = 0; _ambientStageCount = 0; _registerCount = 0; _lightFalloffImage = null; _entityGui = 0; _shouldCreateBackSides = false; _editorImageName = null; _fogLight = false; _blendLight = false; _ambientLight = false; _noFog = false; _hasSubview = false; _allowOverlays = true; _unsmoothedTangents = false; _userInterface = null; _referenceCount = 0; /*editorAlpha = 1.0;*/ _spectrum = 0; _polygonOffset = 0; _suppressInSubview = false; _portalSky = false; _decalInfo.StayTime = 10000; _decalInfo.FadeTime = 4000; _decalInfo.Start = new float[] { 1, 1, 1, 1 }; _decalInfo.End = new float[] { 0, 0, 0, 0 }; }
private void ParseDeform(idLexer lexer) { idToken token = lexer.ExpectAnyToken(); if(token == null) { return; } string tokenValue = token.ToString(); string tokenLower = tokenValue.ToLower(); if(tokenLower == "sprite") { _deformType = DeformType.Sprite; _cullType = CullType.TwoSided; this.MaterialFlag = MaterialFlags.NoShadows; } else if(tokenLower == "tube") { _deformType = DeformType.Tube; _cullType = CullType.TwoSided; this.MaterialFlag = MaterialFlags.NoShadows; } else if(tokenLower == "flare") { _deformType = DeformType.Flare; _cullType = CullType.TwoSided; _deformRegisters[0] = ParseExpression(lexer); this.MaterialFlag = MaterialFlags.NoShadows; } else if(tokenLower == "expand") { _deformType = DeformType.Expand; _deformRegisters[0] = ParseExpression(lexer); } else if(tokenLower == "move") { _deformType = DeformType.Move; _deformRegisters[0] = ParseExpression(lexer); } else if(tokenLower == "turbulent") { _deformType = DeformType.Turbulent; if((token = lexer.ExpectAnyToken()) == null) { lexer.Warning("deform particle missing particle name"); this.MaterialFlag = MaterialFlags.Defaulted; } else { _deformDecl = idE.DeclManager.FindType(DeclType.Table, token.ToString(), true); _deformRegisters[0] = ParseExpression(lexer); _deformRegisters[1] = ParseExpression(lexer); _deformRegisters[2] = ParseExpression(lexer); } } else if(tokenLower == "eyeball") { _deformType = DeformType.Eyeball; } else if(tokenLower == "particle") { _deformType = DeformType.Particle; if((token = lexer.ExpectAnyToken()) == null) { lexer.Warning("deform particle missing particle name"); this.MaterialFlag = MaterialFlags.Defaulted; } else { _deformDecl = idE.DeclManager.FindType(DeclType.Particle, token.ToString(), true); } } else if(tokenLower == "particle2") { _deformType = DeformType.Particle2; if((token = lexer.ExpectAnyToken()) == null) { lexer.Warning("deform particle missing particle name"); this.MaterialFlag = MaterialFlags.Defaulted; } else { _deformDecl = idE.DeclManager.FindType(DeclType.Table, token.ToString(), true); _deformRegisters[0] = ParseExpression(lexer); _deformRegisters[1] = ParseExpression(lexer); _deformRegisters[2] = ParseExpression(lexer); } } else { lexer.Warning("Bad deform type '{0}'", tokenValue); this.MaterialFlag = MaterialFlags.Defaulted; } }
private static extern void Pass_SetCullType(IntPtr Pass, CullType Mode);
void CompileShader(string vertexSrc, string fragmentSrc) { void GetUniform(string line) { var elements = line.Split(' '); string type = elements[1]; string name = elements[2].Trim(';'); Debug.Log($"Found uniform: {name} of type {type}"); //TODO Add to dictionary/list/whatever uniforms.Add(name, new Uniform(name, GetUniformLocation(name), this, null)); } void CheckForUniforms(string src) { var lines = src.Split('\n'); foreach (var line in lines) { if (line.Contains("uniform") && !line.StartsWith("//") && !line.Contains("layout(std140)")) { GetUniform(line); } } } void CheckForIncludes() { Check(ref vertexSrc); Check(ref fragmentSrc); void Check(ref string source) { var lines = source.Split('\n'); foreach (var line in lines) { if (line.StartsWith("#include ")) { string inc = line.Split(' ')[1].Trim('"'); string location = "Resources/Shaders/" + inc; var entry = AssetDatabase.GetPackageFile()[location]; MemoryStream outputStream = new MemoryStream(); entry.Extract(outputStream); string text = Encoding.ASCII.GetString(outputStream.ToArray()); text = text.Replace("?", "").Replace("\r", "").Replace("\t", ""); string file = text; source = source.Replace(line, file); } } } } void CheckForQueue() { var lines = fragmentSrc.Split('\n'); foreach (var line in lines) { if (line.StartsWith("#queue")) { var types = line.Split(' '); var type = types[1]; if (type == "transparent") { IsTransparent = true; } else { IsTransparent = false; } fragmentSrc = fragmentSrc.Replace(line, ""); } } } void CheckForBlending() { var lines = fragmentSrc.Split('\n'); foreach (var line in lines) { if (line.StartsWith("#blend")) { var types = line.Split(' '); var type = types[1]; if (type == "none") { Blending = BlendType.None; } else if (type == "oneminus") { Blending = BlendType.OneMinus; } fragmentSrc = fragmentSrc.Replace(line, ""); } } } void CheckForCulling() { var lines = fragmentSrc.Split('\n'); foreach (var line in lines) { if (line.StartsWith("#culling")) { var types = line.Split(' '); var type = types[1]; if (type == "front") { CullingType = CullType.Front; } else if (type == "none") { CullingType = CullType.None; } else if (type == "back") { CullingType = CullType.Back; } fragmentSrc = fragmentSrc.Replace(line, ""); } } } int vertShader = 0, fragShader = 0; CheckForIncludes(); CheckForQueue(); CheckForBlending(); CheckForCulling(); vertShader = GL.CreateShader(ShaderType.VertexShader); GL.ShaderSource(vertShader, vertexSrc); fragShader = GL.CreateShader(ShaderType.FragmentShader); GL.ShaderSource(fragShader, fragmentSrc); GL.CompileShader(vertShader); string infoLogVert = GL.GetShaderInfoLog(vertShader); if (infoLogVert != System.String.Empty) { //Debug.Assert(infoLogVert); throw new Exception("Vertex Shader " + vertShader + " failed to compile!\n" + infoLogVert); } else { Debug.Log($"VertexContainer shader {vertShader} compiled successfully!"); } GL.CompileShader(fragShader); string infoLogFrag = GL.GetShaderInfoLog(fragShader); if (infoLogFrag != System.String.Empty) { throw new Exception("FragShader " + fragShader + " failed to compile!\n" + infoLogFrag); } else { Debug.Log($"Fragment shader {fragShader} compiled successfully!"); } Handle = GL.CreateProgram(); GL.AttachShader(Handle, vertShader); GL.AttachShader(Handle, fragShader); GL.LinkProgram(Handle); GL.DetachShader(Handle, vertShader); GL.DetachShader(Handle, fragShader); GL.DeleteShader(vertShader); GL.DeleteShader(fragShader); CheckForUniforms(vertexSrc); CheckForUniforms(fragmentSrc); }
public Cull(CullType side) { this.Side = side; }
public Cull() { this.Side = CullType.Back; }