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 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); }