· Гостей: 1
· Пользователей: 0
· Всего пользователей: 7,142
· Новый пользователь: Sarahseato
|
|
|
Урок 7. Как загружать и использовать текстуры |
|
Загрузка текстуры из файла. Передача текстуры в шейдер и использование HLSL для наложения текстуры на 3D-объект.
Шаг 1. Начнём с изменения типа используемых вершин. Раньше мы использовали вершины в которых можно было указывать позицию и цвет. Теперь же нам нужны текстурные координаты и цвет соответственно не нужен, так как цвет будет определяться текстурой. Изменим тип массива вершин с VertexPositionColor на VertexPositionTexture.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
class Program : Game { // графический компонент GraphicsDeviceManager graphics; // массив вершин VertexPositionColor[] vertexList; VertexPositionTexture[] vertexList; // массив индексов int[] indexList; // описание формата вершин VertexDeclaration vertexDeclaration; // эффект (шейдер) Effect effect; // счетчик времени float time;
|
Шаг 2. В методе СreateVertexList() во-первых, так же нужно заменить тип вершин на VertexPositionTexture. Во-вторых, заметьте что у вершин типа VertexPositionTexture конструктор принимает не цвет вершины, а текстурные координаты описываемые структурой типа Vector2. Координаты текстуры задаются в диапазоне 0...1. Первая координата описывает Х, вторая - Y в двухмерной текстуре.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
private void СreateVertexList() { // создать массив-контейнер для хранения трёх вершин vertexList = new VertexPositionTexture[8]; // нижний набор вершин vertexList[0] = new VertexPositionTexture(new Vector3(-1.0f, -1.0f, 1.0f), new Vector2(0, 1)); vertexList[1] = new VertexPositionTexture(new Vector3(1.0f, -1.0f, 1.0f), new Vector2(1, 1)); vertexList[2] = new VertexPositionTexture(new Vector3(-1.0f, -1.0f, -1.0f), new Vector2(0, 0)); vertexList[3] = new VertexPositionTexture(new Vector3(1.0f, -1.0f, -1.0f), new Vector2(1, 0)); // верхний набот вершин vertexList[4] = new VertexPositionTexture(new Vector3(-1.0f, 1.0f, 1.0f), new Vector2(1, 1)); vertexList[5] = new VertexPositionTexture(new Vector3(1.0f, 1.0f, 1.0f), new Vector2(0, 1)); vertexList[6] = new VertexPositionTexture(new Vector3(-1.0f, 1.0f, -1.0f), new Vector2(1, 0)); vertexList[7] = new VertexPositionTexture(new Vector3(1.0f, 1.0f, -1.0f), new Vector2(0, 0)); }
|
Шаг 3. В метод DrawCube() так же нужно внести изменения связанные со сменой типа используемых вершин.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
void DrawCube() { // использовать для отрисовки эффект BasicEffect effect.Begin(); // начать отрисовку первого прохода effect.CurrentTechnique.Passes[0].Begin(); // указать описание формата вершин graphics.GraphicsDevice.VertexDeclaration = vertexDeclaration; // отключить отсечение невидимых поверхностей graphics.GraphicsDevice.RenderState.CullMode = CullMode.None; // нарисовать куб используя массив вершин и индексов graphics.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionTexture>( PrimitiveType.TriangleList, // тип примитивов vertexList, // массив вершин 0, // позиция первой используемой вершины 8, // кол-во используемых вершин indexList, // массив индексов 0, // позиция первого используемого индекса 12); // кол-во выводимых примитивов // завершить первый проход effect.CurrentTechnique.Passes[0].End(); // завершить использование эффекта BasicEffect effect.End(); }
|
Шаг 4. Начнём наконец работать с текстурой. Добавте в класс Program поле texture типа Texture2D. В этом поле будет храниться двухмерная текстура.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
class Program : Game { // графический компонент GraphicsDeviceManager graphics; // массив вершин VertexPositionTexture[] vertexList; // массив индексов int[] indexList; // описание формата вершин VertexDeclaration vertexDeclaration; // эффект (шейдер) Effect effect; // счетчик времени float time; // текстура Texture2D texture;
|
Шаг 5. В метод LoadContent() добавте вызов метода СreateTexture(), в котором позже мы будем загружать текстуру из файла.
1 2 3 4 5 6 7 8 9 10 11 12
|
protected override void LoadContent() { СreateVertexList(); // создать вершины СreateIndexList(); // создать индексы СreateEffect(); // загрузить шейдер СreateTexture(); // загрузить текстуру // создать описание формата вершин vertexDeclaration = new VertexDeclaration( graphics.GraphicsDevice, VertexPositionTexture.VertexElements); }
|
Шаг 6. Добавте в класс Program метод СreateTexture().
1 2 3
|
private void СreateTexture() { }
|
Шаг 7. Добавте в метод СreateTexture() код загрузки текстуры из файла с помощью статического метода FromFile() классаTexture2D.
1 2 3 4 5 6 7
|
private void СreateTexture() { // загрузить текстуру из файла texture = Texture2D.FromFile( graphics.GraphicsDevice, "texture.jpg"); }
|
Шаг 8. Добавте в метод СreateTexture() код передачи загруженной текстуры в шейдер в параметр tex - этот параметр мы опишем позже в файле шейдера.
1 2 3 4 5 6 7 8 9 10
|
private void СreateTexture() { // загрузить текстуру из файла texture = Texture2D.FromFile( graphics.GraphicsDevice, "texture.jpg"); // передаём текстуру в шейдер effect.Parameters["tex"].SetValue(texture); }
|
Шаг 9. Добавте в файл шейдера effect.fx объявление переменных текстуры tex и семплера для текстуры textureSampler.
1 2 3 4 5 6 7 8 9 10 11
|
// матрица трансформации вершин Matrix worldViewProj; // текстура Texture tex; // семплер для текстуры sampler textureSampler = sampler_state { texture=<tex>; };
|
Шаг 10. Измените в файле effect.fx вершинный шейдер с учетом того что теперь в него приходит не цвет вершины, а текстурные координаты. Соответственно выйти из шейдера тоже должны текстурные координаты.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
// вершинный шейдер void VS( // входящие параметры - позиция и цвет вершины координаты текстуры in float4 inPos : POSITION, in float4 inColor : COLOR0, in float2 inTex : TEXCOORD0, // исходящие параметры - позиция и цвет вершины координаты текстуры out float4 outPosition : POSITION, out float4 outColor : COLOR0 out float2 outTex : TEXCOORD0 ) { // трансформируем позицию вершины с помощью матрицы outPosition = mul(inPos, worldViewProj); // копируем цвет вершины outColor = inColor; // копируем координаты текстуры outTex = inTex; }
|
Шаг 11. Измените в файле effect.fx входящий параметр пиксельного шейдера с цвета пикселя на координаты текстуры.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
// пиксельный шейдер void PS( // входящий параметр - цвет пикселя in float4 inColor : COLOR0, // входящий параметр - координаты текстуры in float2 inTex : TEXCOORD0, // исходящий параметр - цвет пикселя out float4 outColor : COLOR0 ) { // копируем цвет пикселя outColor = inColor; }
|
Шаг 12. Измените в файле effect.fx логику пиксельного шейдера: теперь вместо простого копирования цвета пикселя нужно выполнить запрос к двухмерной текстуре для определения цвета текущего пикселя с помощью функции tex2D. Эта функция принимает семплер и текстурные координаты.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
// пиксельный шейдер void PS( // входящий параметр - координаты текстуры in float2 inTex : TEXCOORD0, // исходящий параметр - цвет пикселя out float4 outColor : COLOR0 ) { // копируем цвет пикселя outColor = inColor; // выполняем запрос к текстуре используя координаты текстуры outColor = tex2D(textureSampler, inTex); }
|
Шаг 13. Теперь нехватает самого главного - собственно текстуры. Кликните правой кнопкой по имени проекта в окне "Solution Explorer". В появившемся меню выберите команду "Add -> Existing Item...". С помощью открывшегося окна выберите любой графический файл и добавьте его в проект.
Шаг 14. Назовите дабавленный файл texture.jpg и измените значение опции "Copy to Output Directory" с "Do not copy" на "Copy always" в окне "Properties".
Теперь при запуске приложения вы увидите окно в котором будет нарисован куб покрытый текстурой.В секции загрузок лежит архив с исходным кодом этого и других уроков.
|
Пожалуйста, залогиньтесь для добавления комментария.
|
|
Рейтинг доступен только для пользователей.
Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.
Нет данных для оценки.
|
|
|
Забыли пароль? Запросите новый здесь.
|
Вы должны авторизироваться, чтобы добавить сообщение.
|
|
// передаём текстуру в шейдер
effect.Parameters["tex"].SetValue(texture);
вызывает ошибку - "В экземпляре объекта не задана ссылка на объект."
Гружу текстуру texture = Content.Load<Texture2D>("texture" как в файловом примере, а не как на странице тут.
Хотя может загвозка в том, что я постепенно модифицировал свой пример начиная с первого урока. Но до этого всё работало.