Я изучал рендеринг и кодирование шейдеров или эффектов в Monogame, а также изучил основы добавления функций цвета и формы в свои шейдеры благодаря ресурсам, которые я нашел в Интернете.
Из того, что я узнал на данный момент, мне нужно ввести «*effect: my_effect» в параметре Spritebatch.Begin(), а затем добавить следующее в метод Draw программы:
(КОД РАБОТАЕТ ПРЕКРАСНО)
_spriteBatch.Begin(effect:my_effect);
_spriteBatch.Draw(my_Texture2D, my_Rectangle, Color);
_spriteBatch.End();
Код выше работал нормально, это было приятно. Проблема возникла, когда я добавил Vector2 в параметр Draw, и внезапно шейдер отображался неправильно:
(КОД, КОТОРЫЙ НЕ РАБОТАЕТ)
_spriteBatch.Begin(effect:my_effect);
_spriteBatch.Draw(my_Texture2D, my_Rectangle, my_Vector2, Color);
_spriteBatch.End();
Надеюсь, найдется кто-нибудь, кто сможет помочь, буду признателен.
Вот код ниже (для контекста):
public class Game1 : Game
{
private GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;
Rectangle boxus;
Texture2D color;
Effect first_effect;
Vector2 magi;
public Game1()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
magi = new Vector2(0, 0);
boxus = new Rectangle(0,0, 100, 100);
color = new Texture2D(GraphicsDevice, 1, 1);
first_effect = Content.Load<Effect>("Shader");
color.SetData<Color>(new Color[] { Color.White});
base.Initialize();
}
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
}
protected override void Update(GameTime gameTime)
{
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
_spriteBatch.Begin(effect:first_effect);
_spriteBatch.Draw(color,magi,boxus, Color.White);
_spriteBatch.End();
base.Draw(gameTime);
}
}
Не хорошо:
Большой:
Обновлено: Вот мой собственный код шейдера ниже:
#if OPENGL
#define SV_POSITION POSITION
#define VS_SHADERMODEL vs_3_0
#define PS_SHADERMODEL ps_3_0
#else
#define VS_SHADERMODEL vs_4_0_level_9_1
#define PS_SHADERMODEL ps_4_0_level_9_1
#endif
Texture2D SpriteTexture;
sampler2D SpriteTextureSampler = sampler_state
{
Texture = <SpriteTexture>;
};
struct VertexShaderOutput
{
float4 Position : SV_POSITION;
float4 Color : COLOR0;
float2 TextureCoordinates : TEXCOORD0;
};
float4 MainPS(VertexShaderOutput input) : COLOR
{
float col = tex2D(SpriteTextureSampler, input.TextureCoordinates) * input.Color;
float shape_function = step(input.TextureCoordinates.x, sqrt(input.TextureCoordinates.y));
float3 colorzz = float3(0.9, 0.5, 0.2);
//THE MIX FUNCITON
colorzz = colorzz * (1 - step(0.5, input.TextureCoordinates.y)) + float3(0.0, 0.3, 0.9) * step(0.5, input.TextureCoordinates.y);
float4 output = float4(colorzz * shape_function, 1.0);
return col * output;
}
technique SpriteDrawing
{
pass P0
{
PixelShader = compile PS_SHADERMODEL MainPS();
}
};
ОБНОВЛЕНИЕ: (БОЛЬШОЕ СПАСИБО.)
как вы упомянули, умножьте texCoords
Добавлен дополнительный код для перемещения спрайта.
Конечно, через минуту.
Я рад, что это помогло! Код шейдеров/графики может показаться несколько сложным вначале, но в долгосрочной перспективе оно того стоит.
Проблема связана с двумя различными используемыми методами Draw(...) SpriteBatch.
Первый определяет прямоугольник назначения, то есть ваша текстура «растягивается» до заданного прямоугольника в целевом буфере кадра, следовательно, прямоугольник 100 x 100 в позиции 0, 0.
public void Draw(Texture2D texture, Rectangle destinationRectangle, Color color) {...}
Вторая функция Draw, которую вы использовали вместо этого, принимает прямоугольник, чтобы определить, какая часть исходной текстуры должна быть нарисована и в какой позиции в целевом буфере кадра:
public void Draw(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color) {...}
По этой причине в исходной текстуре предполагался прямоугольник размером 100 x 100 (размер 1 x 1 пиксель), что привело к растягиванию функции Sqrt в 100 раз.
Я думаю, для вашего случая вы могли бы использовать это:
public void Draw(Texture2D texture, Rectangle destinationRectangle, Rectangle? sourceRectangle, Color color) {...}
Здесь x, y прямоугольника назначения тогда будет фактической конечной позицией в целевом буфере кадра, а исходный прямоугольник будет new(0,0,1,1)
Надеюсь, это поможет, дайте мне знать, если вам нужна дополнительная информация. Удерживая клавишу Ctrl, щелкните функцию Draw, чтобы перейти к классу SpriteBatch, где вы сможете увидеть все различные альтернативы функции Draw.
Редактировать 1:
Во-первых, вы можете настроить диапазон значений внутри шейдера по своему усмотрению, умножив значения координат текса или, если достаточно целого числа, отправив исходный прямоугольник следующим образом: new(-1,-1,2,2) (! непроверено) .
Во-вторых, вы можете получить все, что вам нужно, используя эту функцию (масштаб — это ваш окончательный размер):
public void Draw(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth) {...}
Спасибо за разъяснения и понимание, г-н Рафлока. Я настаивал на добавлении Vector2 в метод рисования, потому что думал, что смогу добавить круговое движение, используя функцию синуса и косинуса в координатах xy Vector2, при этом правильно визуализируя шейдер. И это подводит меня к другому вопросу, который я имею в виду: есть ли способ расширить диапазон значений от «-1 до +1» до «-100 до +100» или чего-то в этом роде, поскольку свойства X,Y Прямоугольник может читать только целые числа, а не числа с плавающей запятой?
Вы правы насчет целых чисел прямоугольника, я соответствующим образом отредактировал свой ответ.
Господи, это сработало. Я покажу некоторые обновления позже.
Привет, не могли бы вы также добавить свой собственный код шейдера?