Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


We're also offering banner ads on our site from just $5! 1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


user88

Member Since 17 May 2009
Offline Last Active Jul 16 2014 02:56 AM

#5160256 [DX11] Why we need sRGB back buffer

Posted by user88 on 13 June 2014 - 03:32 AM

Hi,

 

after reading a couple of resources in web about Gamma Correction I still feel confused.

 

In my experiment pixel shader simply outputs linear gradient to backbuffer.

 

 - First case: backbuffer format is not sRGB, value of linear gradient is outputted without any modifications:

ng.jpg

 

 - Second case: backbuffer format is sRGB, value of linear gradient is outputted without any modifications:

g1.jpg

 

 - Third case: backbuffer format is sRGB, value of linear gradient is outputted with correction of pow(u, 1/2.2):

g1div2.2.jpg

 

 - Fourth case: backbuffer format is sRGB, value of linear gradient is outputted with correction of pow(u, 2.2):

g2.2.jpg

 

As you see, first and last results are almost the same. So, my question is why we need sRGB backbuffers plus modifying final output pixel shader if we can simply use non-sRGB texture? The result is almost the same:

pixcmp.jpg




#5045191 Picking objects

Posted by user88 on 21 March 2013 - 04:32 AM

I guess you use c#. Here is c# class representing triangle mesh. You can use picking functionality from this code:

/// <summary:
    /// 3D Geometry that consist from indices, vertices, normals, texture coordinates.
    /// </summary>
    public sealed class TriangleMesh
    {
        private static uint s_internalIdCounter;

	    private BoundingSphere m_boundingSphere;
	    private BoundingBox m_boundingBox;

        /// <summary>
        /// Gets an internal ID that value is unique for each instance.
        /// </summary>
        public uint InternalID { get; private set; }

	    /// <summary>
        /// Gets an array of the indices of the geometry.
        /// </summary>
        public ushort[] Indices { get; private set; }

	    /// <summary>
	    /// Gets an array of the vertices of the geometry.
	    /// </summary>
        public Float3[] Vertices { get; private set; }

	    /// <summary>
	    /// Gets an array of the normals of the geometry. Value can be <c>null</c>.
	    /// </summary>
        public Float3[] Normals { get; private set; }

	    /// <summary>
	    /// Gets an array of the normals of the geometry. Value can be <c>null</c>.
	    /// </summary>
        public Float2[] TexCoords { get; private set; }

	    public TriangleMesh(ushort[] indices, Float3[] vertices, Float3[] normals, Float2[] texCoords)
	    {
            if (indices.Length < 3)
                throw new ArgumentException("The length of the indices array shouldn't be less than 3 elements.", "indices");
            if (vertices.Length < 3)
                throw new ArgumentException("The length of the vertices array shouldn't be less than 3 elements.", "vertices");

	        Indices = indices;
	        Vertices = vertices;
	        Normals = normals;
	        TexCoords = texCoords;

	        unchecked
	        {
	            s_internalIdCounter++;
	        }
	        InternalID = s_internalIdCounter;

	        CalculateBounds();
	    }

        /// <summary>
        /// Calculates a bounding box and a bonding sphere of the geometry.
        /// </summary>
	    private void CalculateBounds()
	    {
	        m_boundingBox = BoundingBox.FromPoints(Vertices);
	        m_boundingSphere = BoundingSphere.FromBox(m_boundingBox);
	    }

        /// <summary>
        /// Gets transformed bounding sphere of the geometry.
        /// </summary>
        /// <param name="transform">Transformation matrix.</param>
        /// <returns>Transformed bounding sphere.</returns>
        public BoundingSphere CalculateBoundingSphere(Float4x4 transform)
        {
            Float3 center = Float3.TransformCoordinate(m_boundingSphere.Center, transform);
            return new BoundingSphere(center, m_boundingSphere.Radius);
        }

        /// <summary>
        /// Gets transformed bounding box of the geometry.
        /// </summary>
        /// <param name="transform">Transformation matrix.</param>
        /// <returns>Transformed bounding box.</returns>
        public BoundingBox CalculateBoundingBox(Float4x4 transform)
        {
            Float3 min = Float3.TransformCoordinate(m_boundingBox.Minimum, transform);
            Float3 max = Float3.TransformCoordinate(m_boundingBox.Maximum, transform);
            return new BoundingBox(min, max);
        }

        /// <summary>
        /// Determines whether a ray intersects the geometry.
        /// </summary>
        /// <param name="transform">Transformation matrix of the geometry</param>
        /// <param name="ray">The ray which will be tested for intersection.</param>
        /// <param name="distance">When the method completes, contains the distance at which the ray intersected the plane.</param>
        /// <param name="faceIndex">When the method completes, contains the index of face which the ray intersects.</param>
        /// <returns><c>true</c> if the ray intersects the plane; otherwise, <c>false</c>.</returns>
        public bool Intersects(Float4x4 transform, Ray ray, out float distance, out int faceIndex)
        {
            float u, v;
            return Intersects(transform , ray, out distance, out faceIndex, out u, out v);
        }

        /// <summary>
        /// Determines whether a ray intersects the geometry.
        /// </summary>
        /// <param name="transform">Transformation matrix of the geometry</param>
        /// <param name="ray">The ray which will be tested for intersection.</param>
        /// <param name="distance">When the method completes, contains the distance at which the ray intersected the plane.</param>
        /// <param name="faceIndex">When the method completes, contains the index of face which the ray intersects.</param>
        /// <param name="u">Barycentric U of face which the ray intersects.</param>
        /// <param name="v">Barycentric V of face which the ray intersects.</param>
        /// <returns><c>true</c> if the ray intersects the plane; otherwise, <c>false</c>.</returns>
        public bool Intersects(Float4x4 transform, Ray ray, out float distance, out int faceIndex, out float u, out float v)
        {
            // Convert ray to model space
            Float3 near = ray.Position;
            Float3 dir = ray.Direction;
            transform.Invert();
            Float3 tmp = near;
            Float3.TransformCoordinate(ref tmp, ref transform, out near);
            tmp = dir;
            Float3.TransformNormal(ref tmp, ref transform, out dir);
            Ray modelSpaceRay = new Ray(near, dir);

            // Test bounding sphere first
            BoundingSphere bs = CalculateBoundingSphere(transform);
            if (Ray.Intersects(ray, bs, out distance))
            {
                if (Indices != null && Indices.Length > 0)
                {
                    // Intersect indexed geometry
                    for (faceIndex = 0; faceIndex < Indices.Length; faceIndex += 3)
                    {
                        Float3 vertex1 = Vertices[Indices[faceIndex]];
                        Float3 vertex2 = Vertices[Indices[faceIndex + 1]];
                        Float3 vertex3 = Vertices[Indices[faceIndex + 2]];

                        if (Ray.Intersects(modelSpaceRay, vertex1, vertex2, vertex3, out distance, out u, out v))
                        {
                            return true;
                        }
                    }
                }
                else
                {
                    // Intersect non-indexed geometry
                    for (faceIndex = 0; faceIndex < Vertices.Length; faceIndex += 3)
                    {
                        Float3 vertex1 = Vertices[faceIndex];
                        Float3 vertex2 = Vertices[faceIndex + 1];
                        Float3 vertex3 = Vertices[faceIndex + 2];

                        if (Ray.Intersects(modelSpaceRay, vertex1, vertex2, vertex3, out distance, out u, out v))
                        {
                            return true;
                        }
                    }
                }
            }

            faceIndex = -1;
            distance = u = v = -1f;
            return false;
        }

        /// <summary>
        /// Determines whether a ray intersects the geometry.
        /// </summary>
        /// <param name="transform">Transformation matrix of the geometry</param>
        /// <param name="ray">The ray which will be tested for intersection.</param>
        /// <param name="distance">When the method completes, contains the distance at which the ray intersected the plane.</param>
        /// <param name="faceIndex">When the method completes, contains the index of face which the ray intersects.</param>
        /// <param name="hits">All intersection hits.</param>
        /// <returns><c>true</c> if the ray intersects the plane; otherwise, <c>false</c>.</returns>
        public bool Intersects(Float4x4 transform, Ray ray, out float distance, out int faceIndex, out IntersectInformation[] hits)
        {
            var hitsList = new List<IntersectInformation>();
            
            float curDistance;
            int curIndex;
            
            distance = float.MaxValue;
            faceIndex = -1;

            // Create bounding sphere before inverting transform matrix
            BoundingSphere bs = CalculateBoundingSphere(transform);
            
            // Convert ray to model space
            Float3 near = ray.Position;
            Float3 dir = ray.Direction;
            transform.Invert();
            Float3 tmp = near;
            Float3.TransformCoordinate(ref tmp, ref transform, out near);
            tmp = dir;
            Float3.TransformNormal(ref tmp, ref transform, out dir);
            Ray modelSpaceRay = new Ray(near, dir);

            // Test bounding sphere first
            if (Ray.Intersects(ray, bs, out curDistance))
            {
                if (Indices != null && Indices.Length > 0)
                {
                    // Intersect indexed geometry
                    for (curIndex = 0; curIndex < Indices.Length; curIndex += 3)
                    {
                        Float3 vertex1 = Vertices[Indices[curIndex]];
                        Float3 vertex2 = Vertices[Indices[curIndex + 1]];
                        Float3 vertex3 = Vertices[Indices[curIndex + 2]];

                        float u, v;
                        if (Ray.Intersects(modelSpaceRay, vertex1, vertex2, vertex3, out curDistance, out u, out v))
                        {
                            if (curDistance < distance)
                            {
                                distance = curDistance;
                                faceIndex = curIndex / 3;
                            }

                            var hit = new IntersectInformation
                                          {
                                              Distance = curDistance,
                                              FaceIndex = faceIndex,
                                              U = u,
                                              V = v
                                          };
                            hitsList.Add(hit);
                        }
                    }
                }
                else
                {
                    // Intersect non-indexed geometry
                    for (curIndex = 0; curIndex < Vertices.Length; curIndex += 3)
                    {
                        Float3 vertex1 = Vertices[curIndex];
                        Float3 vertex2 = Vertices[curIndex + 1];
                        Float3 vertex3 = Vertices[curIndex + 2];

                        float u, v; 
                        if (Ray.Intersects(modelSpaceRay, vertex1, vertex2, vertex3, out curDistance, out u, out v))
                        {
                            if (curDistance < distance)
                            {
                                distance = curDistance;
                                faceIndex = curIndex / 3;
                            }

                            var hit = new IntersectInformation
                            {
                                Distance = curDistance,
                                FaceIndex = faceIndex,
                                U = u,
                                V = v
                            };
                            hitsList.Add(hit);
                        }
                    }
                }
            }

            hits = hitsList.ToArray();
            return hits.Length > 0;
        }
    }

 

Also ray you have to get from picked pixel on screen rather than from near/far. Have a look to this code:

 

void CalculatePickRay(int x, int y, int width, int height, float near, Float4x4 view, Float4x4 projection, out Float3 pickRayDir, out Float3 pickRayOrig)
        {
            pickRayDir.X = (((2.0f * x) / width) - 1);
            pickRayDir.Y = -(((2.0f * y) / height) - 1);
            pickRayDir.Z = 1.0f;

            projection.M41 = 0;
            projection.M42 = 0;
            projection.M43 = 0;
            projection.M44 = 1;
            projection.Invert();
            Float3 tmp = pickRayDir;
            Float3.TransformNormal(ref tmp, ref projection, out pickRayDir);

            // Get the inverse view matrix
            view.Invert();
            tmp = pickRayDir;
            Float3.TransformNormal(ref tmp, ref view, out pickRayDir);
            pickRayDir.Normalize();

            pickRayOrig.X = view.M41;
            pickRayOrig.Y = view.M42;
            pickRayOrig.Z = view.M43;

            // calc origin as intersection with near frustum
            pickRayOrig += pickRayDir * near;
        }



#5045180 Picking objects

Posted by user88 on 21 March 2013 - 03:44 AM

- how do I connect those classes with image on the screen, image, taken from buffers ?

 

Have already implemented the basic functionality of picking. I mean Pick ray calculation, from picked screen coordinates, etc?

 

In case you have a lot of 3D objects in scene you can make the map table of relationships between 3D object in scene and object in your application data model. You have to do it once per scene/level creation.




#5043048 Applying light effects and reflection

Posted by user88 on 14 March 2013 - 07:55 AM

I don't know where to find or how to calculate normal on each vertice, so I tried to make  reflection map, but with no desired result...

 

There is a lot of information conerning this in a web. I.E. here http://www.riemers.net:

            for (int i = 0; i < indices.Length / 3; i++)
             {
                 Vector3 firstvec = vertices[indices[i*3+1]].Position-vertices[indices[i*3]].Position;
                 Vector3 secondvec = vertices[indices[i*3]].Position-vertices[indices[i*3+2]].Position;
                 Vector3 normal = Vector3.Cross(firstvec, secondvec);
                 normal.Normalize();
                 vertices[indices[i * 3]].Normal += normal;
                 vertices[indices[i * 3 + 1]].Normal += normal;
                 vertices[indices[i * 3 + 2]].Normal += normal;
             }



#5008108 SlimDX Directx11 Text Rendering Problem

Posted by user88 on 07 December 2012 - 07:23 AM

Have you checked debug output of Direct3D? maybe there are some errors..


#4768373 [DX9,SlimDX,ATI] Incorrect saving surface to file

Posted by user88 on 02 February 2011 - 02:31 AM

Hello, i have solved this problem. I don't know why, but some ATI graphics adapters have problems with stretch rectangle when destination surface is the render target surface. All works good when destination surface is the surface of dynamic texture.

Here is the old code (in c#):
        	using (Surface src = Device.GetRenderTarget(renderTargetIndex))
        	{
            	SurfaceDescription srcDesc = src.Description;
            	format = srcDesc.Format;
            	Rectangle srcRect = new Rectangle(0, 0, width, height);
            	dst = Surface.CreateRenderTarget(Device, width, height, format, MultisampleType.None, 0, true);
            	Rectangle dstRect = new Rectangle(0, 0, width, height);
            	Device.StretchRectangle(src, srcRect, dst, dstRect, TextureFilter.None);
        	}
And new working code:
        	using (Surface src = Device.GetRenderTarget(0))
        	{
            	Surface nonMsaaSrc = src;
            	SurfaceDescription srcDesc = src.Description;

            	bool msaaOn = srcDesc.MultisampleType != MultisampleType.None;
            	if (msaaOn)
            	{
                	nonMsaaSrc = Surface.CreateRenderTarget(Device, srcDesc.Width, srcDesc.Height, srcDesc.Format, MultisampleType.None, 0, false);
                	Device.StretchRectangle(src, nonMsaaSrc, TextureFilter.None);
            	}

            	result = new Texture(Device, srcDesc.Width, srcDesc.Height, 1, Usage.Dynamic, srcDesc.Format, Pool.SystemMemory);
            	Surface dst = result.GetSurfaceLevel(0);
            	Device.GetRenderTargetData(nonMsaaSrc, dst);

            	if (msaaOn) nonMsaaSrc.Dispose();
        	}



#4620561 [SlimDX] Anti-aliasing?

Posted by user88 on 18 March 2010 - 01:47 AM

Quote:
Original post by Mathy
Also, how would I programmatically see how many quality levels the graphics card supports etc?


Here is a code snippet from SlimDX SDK 2009 Simple Framework:

static void BuildMultisampleTypeList(SettingsCombo9 combo)
{
List<MultisampleType> possibleMultisampleTypes = new List<MultisampleType>
{
MultisampleType.None,
MultisampleType.NonMaskable,
MultisampleType.TwoSamples,
MultisampleType.ThreeSamples,
MultisampleType.FourSamples,
MultisampleType.FiveSamples,
MultisampleType.SixSamples,
MultisampleType.SevenSamples,
MultisampleType.EightSamples,
MultisampleType.NineSamples,
MultisampleType.TenSamples,
MultisampleType.ElevenSamples,
MultisampleType.TwelveSamples,
MultisampleType.ThirteenSamples,
MultisampleType.FourteenSamples,
MultisampleType.FifteenSamples,
MultisampleType.SixteenSamples
};
int quality;
foreach (MultisampleType type in possibleMultisampleTypes)
{
if (GraphicsDeviceManager.Direct3D9Object.CheckDeviceMultisampleType(combo.AdapterOrdinal, combo.DeviceType, // Direct3D9Object is of SlimDX.Direct3D9.Direct3D type
combo.AdapterFormat, combo.Windowed, type, out quality))
{
combo.MultisampleTypes.Add(type);
combo.MultisampleQualities.Add(quality); // note, quality (or quality - 1, can't remember) is highest value of quality level in current multisample type
}
}
}
}






PARTNERS