public void setupSprites(SInstancedSpriteData instanceData) { _backgroundSpriteIdx = instanceData.requestSlot(); _overlaySpriteIdx = instanceData.requestSlot(); instanceData.writeRect(_backgroundSpriteIdx, _backgroundRect); instanceData.writeRect(_overlaySpriteIdx, _overlayRect); }
public void setupSprites(SInstancedSpriteData instanceData) { var numElements = Math.Max(_rects.Length, _scales.Length); _spriteSlotIdxs = instanceData.requestSlots(numElements); for (int i = 0; i < _rects.Length; ++i) { instanceData.writeRect(_spriteSlotIdxs[i], _rects [i]); } for (int i = 0; i < _scales.Length; ++i) { instanceData.writeMasterScale(_spriteSlotIdxs [i], _scales [i]); } }
//public SLaserBurnParticlesObject laserBurnParticlesObject { // get { return _laserBurnParticles; } //} public SLaserManager(SSScene beamScene3d, SSScene occDiskScene, SSScene flareScene2d, int sprite2dCapacity = 1000, int laserBurnParticlesCapacity = 500) { _beamScene3d = beamScene3d; _occDiskScene = occDiskScene; _flareScene2d = flareScene2d; _2dEffectInstanceData = new SInstancedSpriteData(sprite2dCapacity); _2dEffectRenderer = new SSInstancedSpriteRenderer(_beamScene3d, _2dEffectInstanceData); _2dEffectRenderer.Name = "laser manager's 2d screen effect renderer"; _2dEffectRenderer.renderState.alphaBlendingOn = true; _2dEffectRenderer.renderState.blendFactorSrc = BlendingFactorSrc.SrcAlpha; _2dEffectRenderer.renderState.blendFactorDest = BlendingFactorDest.One; //_2dEffectRenderer.renderMode = SSInstancedMeshRenderer.RenderMode.GpuInstancing; _flareScene2d.AddObject(_2dEffectRenderer); _beamScene3d.preRenderHooks += this._update; _maxBurnParticlesPerObject = laserBurnParticlesCapacity; }
public void updateSprites(SInstancedSpriteData instanceData, ref RectangleF clientRect, ref Vector3 cameraPos, ref Matrix4 camera3dView, ref Matrix4 camera3dProj) { Matrix4 camera3dViewProjMat = camera3dView * camera3dProj; if (_sunDiskOccObj != null) { Matrix4 viewInverted = _sunDiskOccScene.renderConfig.invCameraViewMatrix.Inverted(); Vector3 viewRight = Vector3.Transform(Vector3.UnitX, viewInverted).Normalized(); Vector3 viewUp = Vector3.Transform(Vector3.UnitY, viewInverted).Normalized(); _sunDiskOccPos = OpenTKHelper.WorldToScreen(_sunDiskOccObj.Pos, ref camera3dViewProjMat, ref clientRect); float bbFullEstimate; // note that it is assumed that the sun object is fully symmertircal when it is in view if (_sunDiskOccObj.renderState.matchScaleToScreenPixels) { _sunDiskScreenSize = 2f * _sunDiskOccObj.Scale.Xy; bbFullEstimate = (float)Math.PI * _sunDiskOccObj.Scale.X * _sunDiskOccObj.Scale.Y; } else { Vector3 occRightMost = _sunDiskOccObj.Pos + viewRight * _sunDiskOccObj.Scale.X; Vector3 occTopMost = _sunDiskOccObj.Pos + viewUp * _sunDiskOccObj.Scale.Y; Vector2 occRightMostPt = OpenTKHelper.WorldToScreen(occRightMost, ref camera3dViewProjMat, ref clientRect); Vector2 occTopMostPt = OpenTKHelper.WorldToScreen(occTopMost, ref camera3dViewProjMat, ref clientRect); _sunDiskScreenSize = 2f * new Vector2(occRightMostPt.X - _sunDiskOccPos.X, _sunDiskOccPos.Y - occTopMostPt.Y); bbFullEstimate = (float)Math.PI * (float)_sunDiskScreenSize.X * (float)_sunDiskScreenSize.Y / 4f; } _sunDiskOccIntensity = Math.Min((float)_sunDiskOccObj.OcclusionQueueryResult / bbFullEstimate, 1f); } int numElements = _spriteSlotIdxs.Length; if (_sunDiskOccIntensity <= 0f) { // hide all sprites for (int i = 0; i < numElements; ++i) { instanceData.writePosition(_spriteSlotIdxs [i], new Vector2(float.NaN)); // hide all sprites } } else { Vector2 compScale = new Vector2(Math.Max(_sunDiskScreenSize.X, _sunDiskScreenSize.Y) * Math.Min(1.5f, 1f / (1f - _sunDiskOccIntensity))); Vector2 center = new Vector2(clientRect.X, clientRect.Y) + new Vector2(clientRect.Width, clientRect.Height) / 2f; Vector2 towardsCenter = center - _sunDiskOccPos; var color4 = _sunDiskOccObj.MainColor; color4.A = _sunDiskOccIntensity; for (int i = 0; i < numElements; ++i) { int writeIdx = _spriteSlotIdxs [i]; instanceData.writeComponentScale(writeIdx, compScale); instanceData.writeColor(writeIdx, color4); Vector2 spriteCenter = _sunDiskOccPos + towardsCenter * 2.5f / (float)numElements * (float)i; instanceData.writePosition(_spriteSlotIdxs[i], spriteCenter); } } }
public void releaseSprites(SInstancedSpriteData instancesData) { instancesData.releaseSlots(_spriteSlotIdxs); }
public void updateSprites(SInstancedSpriteData instanceData, ref RectangleF clientRect, ref Vector3 cameraPos, ref Matrix4 camera3dView, ref Matrix4 camera3dProj) { var beam = _laser.beam(_beamId); var ray = beam.rayWorld(); var laserParams = _laser.parameters; var beamSrcInViewSpace = Vector3.Transform(beam.startPosWorld, camera3dView); bool hideSprites = true; Vector3 intersectPt3d; if (beamSrcInViewSpace.Z < 0f) { Matrix4 cameraViewProjMat3d = camera3dView * camera3dProj; // extract a near plane from the camera view projection matrix // https://www.opengl.org/discussion_boards/showthread.php/159332-Extract-clip-planes-from-projection-matrix SSPlane3d nearPlane = new SSPlane3d() { A = cameraViewProjMat3d.M14 + cameraViewProjMat3d.M13, B = cameraViewProjMat3d.M24 + cameraViewProjMat3d.M23, C = cameraViewProjMat3d.M34 + cameraViewProjMat3d.M33, D = cameraViewProjMat3d.M44 + cameraViewProjMat3d.M43 }; if (nearPlane.intersects(ref ray, out intersectPt3d)) { #if false Console.WriteLine("camera at world pos = " + cameraPos); Console.WriteLine("camera in screen pos = " + OpenTKHelper.WorldToScreen( cameraPos, ref cameraViewProjMat3d, ref clientRect)); Console.WriteLine("screen hit at world pos = " + intersectPt3d); #endif float lengthToIntersectionSq = (intersectPt3d - beam.startPosWorld).LengthSquared; float beamLengthSq = beam.lengthSqWorld(); if (lengthToIntersectionSq < beamLengthSq) { hideSprites = false; Vector2 drawScreenPos = OpenTKHelper.WorldToScreen( intersectPt3d - ray.dir * 1f, ref cameraViewProjMat3d, ref clientRect); //Console.WriteLine("screen hit at screen pos = " + drawScreenPos); float intensity = _laser.envelopeIntensity * beam.periodicIntensity; Vector2 drawScale = new Vector2(laserParams.hitFlareSizeMaxPx * (float)Math.Exp(intensity)); for (int i = 0; i < _spriteSlotIdxs.Length; ++i) { int writeIdx = _spriteSlotIdxs [i]; instanceData.writePosition(writeIdx, drawScreenPos); instanceData.writeComponentScale(writeIdx, drawScale); instanceData.writeOrientationZ(writeIdx, intensity * 2f * (float)Math.PI); } Color4 backgroundColor = laserParams.backgroundColor; backgroundColor.A = intensity; instanceData.writeColor(_spriteSlotIdxs[(int)SpriteId.coronaBackground], backgroundColor); Color4 overlayColor = laserParams.overlayColor; //overlayColor.A = intensity / _laser.parameters.intensityEnvelope.sustainLevel; overlayColor.A = Math.Min(intensity * 2f, 1f); instanceData.writeColor(_spriteSlotIdxs[(int)SpriteId.coronaOverlay], overlayColor); //System.Console.WriteLine("overlay.alpha == " + overlayColor.A); Color4 ring1Color = laserParams.overlayColor; //ring1Color.A = (float)Math.Pow(intensity, 5.0); ring1Color.A = 0.1f * intensity; instanceData.writeComponentScale(_spriteSlotIdxs[(int)SpriteId.ring1], drawScale * (float)Math.Exp(intensity)); instanceData.writeColor(_spriteSlotIdxs[(int)SpriteId.ring1], ring1Color); //instanceData.writeColor(_spriteSlotIdxs[(int)SpriteId.ring1], Color4.LimeGreen); Color4 ring2Color = laserParams.backgroundColor; //ring2Color.A = (float)Math.Pow(intensity, 10.0); ring2Color.A = intensity * 0.1f; instanceData.writeColor(_spriteSlotIdxs[(int)SpriteId.ring2], ring2Color); //instanceData.writeColor(_spriteSlotIdxs[(int)SpriteId.ring2], Color4.Magenta); } } } if (hideSprites) { // hide sprites for (int i = 0; i < _spriteSlotIdxs.Length; ++i) { instanceData.writeComponentScale(_spriteSlotIdxs[i], Vector2.Zero); } } //System.Console.WriteLine("beam id " + _beamId + " hitting screen at xy " + hitPosOnScreen); }
public void updateSprites(SInstancedSpriteData instanceData, ref RectangleF screenClientRect, ref Vector3 cameraPos, ref Matrix4 camera3dView, ref Matrix4 camera3dProj) { float occDiskScreenAreaUsed = (float)_occDiskObj.OcclusionQueueryResult; if (occDiskScreenAreaUsed <= 0f) { // hide all sprites var nanVec = new Vector2(float.NaN); instanceData.writePosition(_backgroundSpriteIdx, nanVec); instanceData.writePosition(_overlaySpriteIdx, nanVec); return; } var laserParams = _laser.parameters; var beam = _laser.beam(_beamId); float beamIntensity = _laser.envelopeIntensity * beam.periodicIntensity; // position sprites at the beam start in screen space Matrix4 camera3dViewProjMat = camera3dView * camera3dProj; var beamStartScreen = OpenTKHelper.WorldToScreen(beam.startPosWorld, ref camera3dViewProjMat, ref screenClientRect); instanceData.writePosition(_backgroundSpriteIdx, beamStartScreen); instanceData.writePosition(_overlaySpriteIdx, beamStartScreen); // compute screen space needed to occupy the area where the start of the middle's crossbeam // would be displayed Matrix4 viewInverted = camera3dView.Inverted(); Vector3 viewRight = Vector3.Transform(Vector3.UnitX, viewInverted).Normalized(); Vector3 occRightMost = _occDiskObj.Pos + viewRight * laserParams.middleBackgroundWidth; Vector2 occRightMostPt = OpenTKHelper.WorldToScreen(occRightMost, ref camera3dViewProjMat, ref screenClientRect); Vector2 occCenterPt = OpenTKHelper.WorldToScreen(_occDiskObj.Pos, ref camera3dViewProjMat, ref screenClientRect); float crossBeamRadiusScreenPx = Math.Abs(occRightMostPt.X - occCenterPt.X); // write sprite size big enough to cover up the starting section of the cross beam (middle) float scale = Math.Max(laserParams.emissionFlareScreenSizeMin, crossBeamRadiusScreenPx * 2.5f) * beamIntensity; instanceData.writeMasterScale(_backgroundSpriteIdx, scale * 1.2f); instanceData.writeMasterScale(_overlaySpriteIdx, scale * 1f); // add some variety to orientation to make the sprites look less static instanceData.writeOrientationZ(_backgroundSpriteIdx, beamIntensity * 1f * (float)Math.PI); instanceData.writeOrientationZ(_overlaySpriteIdx, beamIntensity * 1f * (float)Math.PI); // color intensity: depends on the dot product between to-camera vector and beam direction; // also depends on how of the occlusion disk area is visible float maxScreenArea = (float)Math.PI * laserParams.emissionOccDiskRadiusPx * laserParams.emissionOccDiskRadiusPx; float occDiskAreaRatio = occDiskScreenAreaUsed / maxScreenArea; //System.Console.WriteLine("occDiskAreaRatio = " + occDiskAreaRatio); Vector3 toCamera = (cameraPos - beam.startPosWorld).Normalized(); float dot = Math.Max(0f, Vector3.Dot(toCamera, beam.directionWorld())); //System.Console.WriteLine("dot = " + dot); var alpha = occDiskAreaRatio * 1.2f * (float)Math.Pow(beamIntensity, 0.1) * (float)Math.Pow(dot, 0.1); alpha = Math.Min(alpha, 1f); // finish background color var backgroundColor = laserParams.backgroundColor; backgroundColor.A = alpha; instanceData.writeColor(_backgroundSpriteIdx, backgroundColor); // finish overlay color var overlayColor = laserParams.overlayColor; overlayColor.A = alpha; instanceData.writeColor(_overlaySpriteIdx, overlayColor); }
public void releaseSprites(SInstancedSpriteData instanceData) { instanceData.releaseSlot(_backgroundSpriteIdx); instanceData.releaseSlot(_overlaySpriteIdx); }