forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   С# (http://forum.boolean.name/forumdisplay.php?f=128)
-   -   Рисование примитивов XNA (http://forum.boolean.name/showthread.php?t=14473)

ІГРОГРАЙКО 26.03.2011 18:00

Рисование примитивов XNA
 
Вложений: 4
Привет!
У меня возникла проблема с коректной отрисовкой примитивов, а точнее полигональной сеткой:
Вложение 13111Вложение 13112
На рисунках видно не коректную работу AlphaBlending... И еще неверное количество отрисованых треугольников...

Вот код метода построения полигональной сетки:
Код:

public Vector3 Initialize3DMesh(int width, int height, int depth)
        {
            vertexDeclaration = new VertexDeclaration(GraphicsDevice, VertexPositionTexture.VertexElements);

            pointListNX = new VertexPositionTexture[depth * 2 * 2];
            pointListNY = new VertexPositionTexture[width * 2 * 2];
            pointListNZ = new VertexPositionTexture[height * 2 * 2];

            for (int ny = 0; ny < depth; ny++)
            {
                for (int nx = 0; nx < 2; nx++)
                {
                    for (int nz = 0; nz < 2; nz++)
                    {
                        pointListNX[(ny * 4) + (nx * 2) + nz] = new VertexPositionTexture(new Vector3((float)nx, (float)(1.0f / depth) * ny, (float)nz), new Vector2((float)nx, (float)nz));
                    }
                }
            }

            for (int nx = 0; nx < width; nx++)
            {
                for (int ny = 0; ny < 2; ny++)
                {
                    for (int nz = 0; nz < 2; nz++)
                    {
                        pointListNY[(nx * 4) + (ny * 2) + nz] = new VertexPositionTexture(new Vector3((float)(1.0f / width) * nx, (float)ny, (float)nz), new Vector2((float)ny, (float)nz));
                    }
                }
            }

            for (int nz = 0; nz < height; nz++)
            {
                for (int nx = 0; nx < 2; nx++)
                {
                    for (int ny = 0; ny < 2; ny++)
                    {
                        pointListNZ[(nz * 4) + (nx * 2) + ny] = new VertexPositionTexture(new Vector3((float)nx, (float)ny, (float)(1.0f / height) * nz), new Vector2((float)nx, (float)ny));
                    }
                }
            }

            triangleStripIndicesNX = LayerBank(depth);
            triangleStripIndicesNY = LayerBank(width);
            triangleStripIndicesNZ = LayerBank(height);

            return new Vector3(width, height, depth);
        }




        private int[] LayerBank(int numberLayers)
        {
            int[] triangleStripIndices = new int[numberLayers * 4];
            for (int y = 0; y < numberLayers; y++)
            {
                for (int i = 0; i < 4; i++)
                {
                    triangleStripIndices[(y * 4) + i] = (y * 4) + i;
                }
            }
            return triangleStripIndices;
        }

Припустим я создаю полигональную сетку 4 х 4 х 4:
Код:

        protected override void LoadContent()
        {
                  VolumeMesh = Initialize3DMesh(4, 4, 4);
        }

Все по ходу работает нормально:
Вложение 13113Вложение 13114
Ну и естественно подходим к блоку Draw:
Код:

        protected override void Draw(GameTime gameTime)
        {
            InitializeTransform(0, rotY, 0);

            GraphicsDevice.Clear(Color.DarkBlue);
            GraphicsDevice.VertexDeclaration = vertexDeclaration;

            GraphicsDevice.RenderState.FillMode = FillMode.Solid;
            GraphicsDevice.RenderState.CullMode = CullMode.None;

            effect.Parameters["WorldViewProj"].SetValue(worldViewProj);
            effect.CurrentTechnique = effect.Techniques["BasicView"];

            GraphicsDevice.RenderState.AlphaBlendEnable = true;
            GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
            GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;

            DrawTriangleStrip(VolumeMesh);
           
            base.Draw(gameTime);
        }




        private void DrawTriangleStrip(Vector3 sizes)
        {
            effect.Begin();
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Begin();
                for (int nx = 0; nx < sizes.Y; nx++)
                {
                    GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionTexture>(
                        PrimitiveType.TriangleStrip,
                        pointListNX,
                        nx * 4,  // vertex buffer offset to add to each element of the index buffer
                        4,  // number of vertices to draw
                        triangleStripIndicesNX,
                        nx * 4,  // first index element to read
                        2  // number of primitives to draw
                    );
                }

                for (int ny = 0; ny < sizes.X; ny++)
                {
                    GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionTexture>(
                        PrimitiveType.TriangleStrip,
                        pointListNY,
                        ny * 4,  // vertex buffer offset to add to each element of the index buffer
                        4,  // number of vertices to draw
                        triangleStripIndicesNY,
                        ny * 4,  // first index element to read
                        2  // number of primitives to draw
                    );
                }

                for (int nz = 0; nz < sizes.Z; nz++)
                {
                    GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionTexture>(
                        PrimitiveType.TriangleStrip,
                        pointListNZ,
                        nz * 4,  // vertex buffer offset to add to each element of the index buffer
                        4,  // number of vertices to draw
                        triangleStripIndicesNZ,
                        nz * 4,  // first index element to read
                        2  // number of primitives to draw
                    );
                }
                pass.End();
            }
            effect.End();
        }

Функция пиксель шейдера:
Код:

return float4(1,1,1,0.1f);
В принципе DrawTriangleStrip() Должен рисовать 4 х 4 х 4 слоя в сетке. А он рисует 2 х 2 х 2...
Почему так?
И как исправить плохой AlphaBlending???

Mr_F_ 26.03.2011 18:11

Ответ: Рисование примитивов XNA
 
полигоны надо сортировать от дальних к ближним, чтобы альфа работала
учитывая что они у тебя пересекаются все друг другом... то придётся изначально в геометрии каждый разделить на кучу маленьких полигонов, полученных при пересечениях и сортировать уже их
либо авось сойдёт просто сортировать и рендерить без записи Z

pax 26.03.2011 18:38

Ответ: Рисование примитивов XNA
 
Я бы попробовал выключить zwrite и рисовать в два прохода - сначала внутренние грани, потом наружные.

ІГРОГРАЙКО 26.03.2011 22:54

Ответ: Рисование примитивов XNA
 
Вложений: 2
Цитата:

Сообщение от Mr_F_ (Сообщение 183822)
полигоны надо сортировать от дальних к ближним, чтобы альфа работала
учитывая что они у тебя пересекаются все друг другом... то придётся изначально в геометрии каждый разделить на кучу маленьких полигонов, полученных при пересечениях и сортировать уже их
либо авось сойдёт просто сортировать и рендерить без записи Z

1. А как сортировать полигоны? Ти имееш в виду, чтоб DrawTriangleStrip() Отрисововала в первую очередь полигодны которие поближе к камере?? Или ето надо чото с шейдером сделать...?
2. А как ето без записи Z???

Цитата:

Сообщение от pax (Сообщение 183826)
Я бы попробовал выключить zwrite и рисовать в два прохода - сначала внутренние грани, потом наружные.

Как выключить zwrite?? И на счет граней - Использовать:
Код:

GraphicsDevice.RenderState.CullMode = CullMode.CullClockwiseFace;
GraphicsDevice.RenderState.CullMode = CullMode.CullCounterClockwiseFace;

???

Как решить проблему с неверной отрисовкой полигонов?
Когда я попробовал сделать так:
Код:

        private void DrawTriangleStrip(Vector3 sizes)
        {
            effect.Begin();
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Begin();
                for (int nx = 0; nx < sizes.Y; nx++)
                {
                    GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionTexture>(
                        PrimitiveType.TriangleStrip,
                        pointListNX,
                        nx * 4,  // vertex buffer offset to add to each element of the index buffer
                        4,  // number of vertices to draw
                        triangleStripIndicesNX,
                        nx,  // first index element to read
                        4   // number of primitives to draw
                    );
                }

                for (int ny = 0; ny < sizes.X; ny++)
                {
                    GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionTexture>(
                        PrimitiveType.TriangleStrip,
                        pointListNY,
                        ny * 4,  // vertex buffer offset to add to each element of the index buffer
                        4,  // number of vertices to draw
                        triangleStripIndicesNY,
                        ny,  // first index element to read
                        4  // number of primitives to draw
                    );
                }

                for (int nz = 0; nz < sizes.Z; nz++)
                {
                    GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionTexture>(
                        PrimitiveType.TriangleStrip,
                        pointListNZ,
                        nz * 4,  // vertex buffer offset to add to each element of the index buffer
                        4,  // number of vertices to draw
                        triangleStripIndicesNZ,
                        nz,  // first index element to read
                        4  // number of primitives to draw
                    );
                }
                pass.End();
            }
            effect.End();
        }

Оно отрисовало верное количество полигонов, но нарисовало и много лишнего:
Вложение 13117Вложение 13118
Что здесь не так я не понимаю... Прежняя версия DrawTriangleStrip() на мой взгляд правильная, но неправильно работает... Посоветуйте мне что нибудь на счет етого...:dontknow:

pax 26.03.2011 23:02

Ответ: Рисование примитивов XNA
 
Цитата:

Сообщение от ІГРОГРАЙКО (Сообщение 183848)
2. А как ето без записи Z???

когда ты пишешь Z - у тебя передняя геометрия не дает отрисоваться геометрии, которая дальше. вот и проблема на твоем первом скриншоте.

UPD: может тут про сорировку найдешь что-то полезное.

ІГРОГРАЙКО 27.03.2011 00:33

Ответ: Рисование примитивов XNA
 
Вложений: 3
Благодарю тебя PAX за хорошие советы!

Дело в том что я на ету полигональную сетку буду клеить 3Д текстуру, так как метод предложеный в VolumeRayCasting_101 - 202 мне не подходит. А с полигональной сеткой работает:
Вложение 13119Вложение 13120
Код шейдера выглядит:
Код:

float4x4 WorldViewProj;

texture3D Volume;

sampler3D SVolume = sampler_state
{
        Texture = <Volume>;
        MinFilter = LINEAR;
        MagFilter = LINEAR;
        MipFilter = LINEAR;
};

struct VS_INPUT
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
};

struct VS_OUTPUT
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
    float4 pos : TEXCOORD1;
};

VS_OUTPUT PositionVS(VS_INPUT input)
{
    VS_OUTPUT output;
       
    output.Position = mul(input.Position, WorldViewProj);
    output.TexCoord = input.TexCoord;
    output.pos = input.Position;

    return output;
}

float4 PixelShaderFunction(VS_OUTPUT input) : COLOR0
{
    float4 outColor = tex3D(SVolume,input.pos);

    return outColor * float4(1,1,1,0.2f);
}

technique BasicView
{
    pass Pass1
    {
        // TODO: set renderstates here.

        VertexShader = compile vs_1_1 PositionVS();
        PixelShader = compile ps_1_1 PixelShaderFunction();
    }
}

Но ети проблемы с отрисовкой полигонов меня затормозили>>:(
...Если камеру опустить пониже:
Вложение 13122
Видно неудавшиеся попытки отрисоватса следующим слоям после первого... А ето никуда не годится!:(

ІГРОГРАЙКО 27.03.2011 17:54

Ответ: Рисование примитивов XNA
 
Вложений: 2
Я пробовал отключать Z - buffer вот результат:

Код:

GraphicsDevice.RenderState.DepthBufferWriteEnable = true;
Вложение 13130
Код:

GraphicsDevice.RenderState.DepthBufferWriteEnable = false;
Вложение 13132

Постоянно изменяется последовательность отображаемых слоёв. Вернее не последовательность, а приоритет отображения (один момент все хорошо, второй - видима часть внутрених слоёв, третий - задних и т. д. в произвольном порядке) Как ето можно исправить?

pax 27.03.2011 19:35

Ответ: Рисование примитивов XNA
 
Сортировка тебя спасет

ІГРОГРАЙКО 05.04.2011 00:55

Ответ: Рисование примитивов XNA
 
Вложений: 1
Привет!

Посмотрел что такое BSP и решыл отказатса от доработки подобной полигональной сетки...
Но увидил другую! :)
На вид оч проста. Но как ее зделать не знаю :dontknow:

Вот:
Вложение 13226

Как можна оптимально сделать последовательность полигонов внутри бокса, так чтобы все полигоны отрисововались перпендикулярно к камере??

Помогите пожалуйста!

pax 05.04.2011 10:26

Ответ: Рисование примитивов XNA
 
Цитата:

Сообщение от ІГРОГРАЙКО (Сообщение 184897)
Как можна оптимально сделать последовательность полигонов внутри бокса, так чтобы все полигоны отрисововались перпендикулярно к камере??

Не вижу на скриншоте перпендикулярных экрану полигонов. Куб разбит "перпендикулярными" экрану плоскостями, но полигоны имеют те же нормали что и у исходного куба.

ІГРОГРАЙКО 05.04.2011 16:33

Ответ: Рисование примитивов XNA
 
Вложений: 2
Цитата:

Сообщение от pax (Сообщение 184920)
Не вижу на скриншоте перпендикулярных экрану полигонов. Куб разбит "перпендикулярными" экрану плоскостями, но полигоны имеют те же нормали что и у исходного куба.

Эсли я понял то что ты хотел сказать, то ты РАХ не прав. Если ето всего навсего разбиение граней Бокса плоскостями, то 3Д текстура внутри бокса бы не отрисовалась (не было бы на чём).
Но суть не в етом.
Меня больше всего беспокоит как релизовать постоянное перестроение етих "плоскостей" или полигонов, как вам удобней, ограниченых гранями бокса при передвижении камеры. Ето что придетса перетаскивать каждую точку каждого полигона в определенное место что вычисляетса какой то страшной матиматической формулой?:??
Вложение 13240Вложение 13241
Помогите! Пишите все что придет на ум...

pax 05.04.2011 16:55

Ответ: Рисование примитивов XNA
 
Так у тебя же вроде не полуичлось создать 3d текстуру? как ты планируешь на такие плигоны, ориентированные на камеру свою текстуру/текстуры вешать.
Я предположил, что ты хочешь разбить свою модель на части и отсортировать их. Значит я ошибся и не так понял, т.к. по скриншоту понятно не было.

Если бы я сам хотел решить такую задачу, то я бы поступил следующим образом:
1. Задал бы расстояние мужду плоскостями.
2. Для каждой грани имеющихся полигонов посчитал точки, лежащие на гранях, соответствующие шагам плоскостей.
3. Объединил бы все найденные точки в группы по удаленности и составил бы для каждой группы новые полигоны.
4. Вместе с этим делом надо было бы считать uvw с трехмерной текстуры.
5. Далее отрисовка.

Но сначала я бы погуглил и поискал алгоритмы, релизующие такой принцип.

ІГРОГРАЙКО 05.04.2011 20:42

Ответ: Рисование примитивов XNA
 
Цитата:

Сообщение от pax (Сообщение 184962)
Так у тебя же вроде не полуичлось создать 3d текстуру? как ты планируешь на такие плигоны, ориентированные на камеру свою текстуру/текстуры вешать.
Я предположил, что ты хочешь разбить свою модель на части и отсортировать их. Значит я ошибся и не так понял, т.к. по скриншоту понятно не было.

Получилось рах :) Я использую класс Texture3D и функицию в шейдере tex3D(), но только без лишних вычислений (т.е. не делаю никакой выборки из симплера).

Спасибо за совет!
Дело в том, что я не знаю как називаетса такой тип построения полигональной сетки. Но если найду, сам выкладу и распишу все как надо...:ok:

Есть чёто похожое но не то: http://www.xnadev.ru/articles.php?article_id=12
Тем кто знает больше - пишите! Не стесняйтесь.. :rolleyes:


Часовой пояс GMT +4, время: 20:55.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot